2022-05-31 08:02:39 +12:00
use std ::collections ::{ BTreeSet , HashMap } ;
2022-04-23 07:46:33 +12:00
use std ::io ::prelude ::* ;
2023-05-03 08:37:12 +12:00
use std ::mem ;
2022-04-23 07:46:33 +12:00
use std ::path ::PathBuf ;
use std ::sync ::atomic ::{ AtomicBool , AtomicUsize , Ordering } ;
use std ::sync ::Arc ;
use crossbeam_channel ::Receiver ;
2023-10-11 07:54:41 +13:00
use fun_time ::fun_time ;
2023-05-03 08:37:12 +12:00
use futures ::channel ::mpsc ::UnboundedSender ;
2023-10-11 07:54:41 +13:00
use log ::debug ;
2022-04-23 07:46:33 +12:00
use mime_guess ::get_mime_extensions ;
use rayon ::prelude ::* ;
2023-10-13 05:48:46 +13:00
use serde ::Serialize ;
2022-04-23 07:46:33 +12:00
2023-05-08 06:54:05 +12:00
use crate ::common ::{ prepare_thread_handler_common , send_info_and_wait_for_ending_all_threads } ;
2023-05-11 07:27:41 +12:00
use crate ::common_dir_traversal ::{ CheckingMethod , DirTraversalBuilder , DirTraversalResult , FileEntry , ProgressData , ToolType } ;
2023-10-05 19:06:47 +13:00
use crate ::common_tool ::{ CommonData , CommonToolData } ;
2022-04-23 07:46:33 +12:00
use crate ::common_traits ::* ;
2022-06-11 04:58:53 +12:00
static DISABLED_EXTENSIONS : & [ & str ] = & [ " file " , " cache " , " bak " , " data " ] ; // Such files can have any type inside
2022-05-17 04:23:07 +12:00
2022-04-23 07:46:33 +12:00
// This adds several workarounds for bugs/invalid recognizing types by external libraries
// ("real_content_extension", "current_file_extension")
2023-05-03 08:37:12 +12:00
const WORKAROUNDS : & [ ( & str , & str ) ] = & [
2022-04-23 07:46:33 +12:00
// Wine/Windows
2022-05-31 08:02:39 +12:00
( " der " , " cat " ) ,
2022-04-23 07:46:33 +12:00
( " exe " , " acm " ) ,
( " exe " , " ax " ) ,
( " exe " , " bck " ) ,
( " exe " , " com " ) ,
( " exe " , " cpl " ) ,
( " exe " , " dll16 " ) ,
2022-06-11 04:58:53 +12:00
( " exe " , " dll " ) ,
2022-04-23 07:46:33 +12:00
( " exe " , " drv16 " ) ,
2022-06-11 04:58:53 +12:00
( " exe " , " drv " ) ,
2022-04-23 07:46:33 +12:00
( " exe " , " ds " ) ,
2022-05-31 08:02:39 +12:00
( " exe " , " efi " ) ,
2022-04-23 07:46:33 +12:00
( " exe " , " exe16 " ) ,
( " exe " , " fon " ) , // Type of font or something else
2022-05-31 08:02:39 +12:00
( " exe " , " mod16 " ) ,
2022-04-23 07:46:33 +12:00
( " exe " , " msstyles " ) ,
2022-05-31 08:02:39 +12:00
( " exe " , " mui " ) ,
2022-06-11 04:58:53 +12:00
( " exe " , " mun " ) ,
2022-04-23 07:46:33 +12:00
( " exe " , " orig " ) ,
2022-06-11 04:58:53 +12:00
( " exe " , " ps1xml " ) ,
( " exe " , " rll " ) ,
( " exe " , " rs " ) ,
( " exe " , " scr " ) ,
2022-05-31 08:02:39 +12:00
( " exe " , " signed " ) ,
( " exe " , " sys " ) ,
2022-04-23 07:46:33 +12:00
( " exe " , " tlb " ) ,
2022-06-11 04:58:53 +12:00
( " exe " , " tsp " ) ,
( " exe " , " vdm " ) ,
2022-04-23 07:46:33 +12:00
( " exe " , " vxd " ) ,
2022-05-31 08:02:39 +12:00
( " exe " , " winmd " ) ,
2022-06-11 04:58:53 +12:00
( " gz " , " loggz " ) ,
2022-05-31 08:02:39 +12:00
( " xml " , " adml " ) ,
2022-06-11 04:58:53 +12:00
( " xml " , " admx " ) ,
( " xml " , " camp " ) ,
( " xml " , " cdmp " ) ,
( " xml " , " cdxml " ) ,
( " xml " , " dgml " ) ,
( " xml " , " diagpkg " ) ,
( " xml " , " gmmp " ) ,
( " xml " , " library-ms " ) ,
( " xml " , " man " ) ,
2022-05-31 08:02:39 +12:00
( " xml " , " manifest " ) ,
2022-06-11 04:58:53 +12:00
( " xml " , " msc " ) ,
2022-05-31 08:02:39 +12:00
( " xml " , " mum " ) ,
2022-06-11 04:58:53 +12:00
( " xml " , " resx " ) ,
( " zip " , " wmz " ) ,
2023-10-05 19:06:47 +13:00
// Games specific extensions - cannot be used here common extensions like zip
( " gz " , " h3m " ) , // Heroes 3
( " zip " , " hashdb " ) , // Gog
2023-10-14 23:59:58 +13:00
( " zip " , " c2 " ) , // King of the Dark Age
( " bmp " , " c2 " ) , // King of the Dark Age
( " avi " , " c2 " ) , // King of the Dark Age
( " exe " , " c2 " ) , // King of the Dark Age
2022-05-17 04:23:07 +12:00
// Other
2023-10-05 19:06:47 +13:00
( " der " , " keystore " ) , // Godot/Android keystore
2022-06-11 04:58:53 +12:00
( " exe " , " pyd " ) , // Python/Mingw
2022-05-31 08:02:39 +12:00
( " gz " , " blend " ) , // Blender
( " gz " , " crate " ) , // Cargo
( " gz " , " svgz " ) , // Archive svg
( " gz " , " tgz " ) , // Archive
2022-06-11 04:58:53 +12:00
( " html " , " dtd " ) , // Mingw
( " html " , " ent " ) , // Mingw
2022-05-31 08:02:39 +12:00
( " html " , " md " ) , // Markdown
2023-10-05 19:06:47 +13:00
( " html " , " svelte " ) , // Svelte
2022-05-31 08:02:39 +12:00
( " jpg " , " jfif " ) , // Photo format
2022-10-23 07:43:06 +13:00
( " m4v " , " mp4 " ) , // m4v and mp4 are interchangeable
2022-05-31 08:02:39 +12:00
( " mobi " , " azw3 " ) , // Ebook format
( " mpg " , " vob " ) , // Weddings in parts have usually vob extension
( " obj " , " bin " ) , // Multiple apps, Czkawka, Nvidia, Windows
( " obj " , " o " ) , // Compilators
( " odp " , " otp " ) , // LibreOffice
( " ods " , " ots " ) , // Libreoffice
( " odt " , " ott " ) , // Libreoffice
( " ogg " , " ogv " ) , // Audio format
2023-10-05 19:06:47 +13:00
( " pem " , " key " ) , // curl, openssl
2023-10-14 23:59:58 +13:00
( " png " , " kpp " ) , // Krita presets
2022-05-31 08:02:39 +12:00
( " pptx " , " ppsx " ) , // Powerpoint
( " sh " , " bash " ) , // Linux
2022-06-11 04:58:53 +12:00
( " sh " , " guess " ) , // GNU
2022-05-31 08:02:39 +12:00
( " sh " , " pl " ) , // Gnome/Linux
( " sh " , " pm " ) , // Gnome/Linux
( " sh " , " py " ) , // Python
( " sh " , " pyx " ) , // Python
( " sh " , " rs " ) , // Rust
( " sh " , " sample " ) , // Git
( " xml " , " bsp " ) , // Quartus
( " xml " , " cbp " ) , // CodeBlocks config
( " xml " , " cfg " ) , // Multiple apps - Godot
( " xml " , " cmb " ) , // Cambalache
( " xml " , " conf " ) , // Multiple apps - Python
( " xml " , " config " ) , // Multiple apps - QT Creator
( " xml " , " dae " ) , // 3D models
( " xml " , " docbook " ) , //
( " xml " , " fb2 " ) , //
2023-10-05 19:06:47 +13:00
( " xml " , " filters " ) , // Visual studio
2022-05-31 08:02:39 +12:00
( " xml " , " gir " ) , // GTK
( " xml " , " glade " ) , // Glade
( " xml " , " iml " ) , // Intelij Idea
( " xml " , " kdenlive " ) , // KDenLive
( " xml " , " lang " ) , // ?
2022-06-11 04:58:53 +12:00
( " xml " , " nuspec " ) , // Nuget
2022-05-31 08:02:39 +12:00
( " xml " , " policy " ) , // SystemD
( " xml " , " qsys " ) , // Quartus
( " xml " , " sopcinfo " ) , // Quartus
( " xml " , " svg " ) , // SVG
( " xml " , " ui " ) , // Cambalache, Glade
( " xml " , " user " ) , // Qtcreator
( " xml " , " vbox " ) , // VirtualBox
( " xml " , " vbox-prev " ) , // VirtualBox
( " xml " , " vcproj " ) , // VisualStudio
2023-05-11 07:27:41 +12:00
( " xml " , " vcxproj " ) , // VisualStudio
2022-05-31 08:02:39 +12:00
( " xml " , " xba " ) , // Libreoffice
( " xml " , " xcd " ) , // Libreoffice files
( " zip " , " apk " ) , // Android apk
2022-06-01 03:52:55 +12:00
( " zip " , " cbr " ) , // Comics
2022-05-31 08:02:39 +12:00
( " zip " , " dat " ) , // Multiple - python, brave
( " zip " , " doc " ) , // Word
( " zip " , " docx " ) , // Word
( " zip " , " jar " ) , // Java
( " zip " , " kra " ) , // Krita
2023-10-14 23:59:58 +13:00
( " zip " , " kgm " ) , // Krita
2022-05-31 08:02:39 +12:00
( " zip " , " nupkg " ) , // Nuget packages
( " zip " , " odg " ) , // Libreoffice
( " zip " , " pptx " ) , // Powerpoint
( " zip " , " whl " ) , // Python packages
2022-06-11 04:58:53 +12:00
( " zip " , " xlsx " ) , // Excel
2022-05-31 08:02:39 +12:00
( " zip " , " xpi " ) , // Firefox extensions
( " zip " , " zcos " ) , // Scilab
// Probably invalid
( " html " , " svg " ) ,
2022-04-23 07:46:33 +12:00
( " xml " , " html " ) ,
2022-05-17 04:23:07 +12:00
// Probably bug in external library
2022-10-23 07:43:06 +13:00
( " msi " , " ppt " ) , // Not sure why ppt is not recognized
( " msi " , " doc " ) , // Not sure why doc is not recognized
( " exe " , " xls " ) , // Not sure why xls is not recognized
2022-04-23 07:46:33 +12:00
] ;
2023-10-13 05:48:46 +13:00
#[ derive(Clone, Serialize) ]
2022-04-23 07:46:33 +12:00
pub struct BadFileEntry {
pub path : PathBuf ,
pub modified_date : u64 ,
pub size : u64 ,
pub current_extension : String ,
pub proper_extensions : String ,
}
2022-06-01 03:52:55 +12:00
2022-04-23 07:46:33 +12:00
#[ derive(Default) ]
pub struct Info {
pub number_of_files_with_bad_extension : usize ,
}
pub struct BadExtensions {
2023-10-05 19:06:47 +13:00
common_data : CommonToolData ,
2022-04-23 07:46:33 +12:00
information : Info ,
files_to_check : Vec < FileEntry > ,
bad_extensions_files : Vec < BadFileEntry > ,
include_files_without_extension : bool ,
}
impl BadExtensions {
pub fn new ( ) -> Self {
Self {
2023-10-05 19:06:47 +13:00
common_data : CommonToolData ::new ( ToolType ::BadExtensions ) ,
information : Info ::default ( ) ,
2022-04-23 07:46:33 +12:00
files_to_check : Default ::default ( ) ,
bad_extensions_files : Default ::default ( ) ,
include_files_without_extension : true ,
}
}
2023-10-15 02:04:45 +13:00
#[ fun_time(message = " find_bad_extensions_files " , level = " info " ) ]
2023-05-03 08:37:12 +12:00
pub fn find_bad_extensions_files ( & mut self , stop_receiver : Option < & Receiver < ( ) > > , progress_sender : Option < & UnboundedSender < ProgressData > > ) {
2023-10-05 19:06:47 +13:00
self . optimize_dirs_before_start ( ) ;
2022-04-23 07:46:33 +12:00
if ! self . check_files ( stop_receiver , progress_sender ) {
2023-10-05 19:06:47 +13:00
self . common_data . stopped_search = true ;
2022-04-23 07:46:33 +12:00
return ;
}
if ! self . look_for_bad_extensions_files ( stop_receiver , progress_sender ) {
2023-10-05 19:06:47 +13:00
self . common_data . stopped_search = true ;
2022-04-23 07:46:33 +12:00
return ;
}
self . debug_print ( ) ;
}
2023-10-15 02:04:45 +13:00
#[ fun_time(message = " check_files " , level = " debug " ) ]
2023-05-03 08:37:12 +12:00
fn check_files ( & mut self , stop_receiver : Option < & Receiver < ( ) > > , progress_sender : Option < & UnboundedSender < ProgressData > > ) -> bool {
2022-04-23 07:46:33 +12:00
let result = DirTraversalBuilder ::new ( )
2023-10-05 19:06:47 +13:00
. root_dirs ( self . common_data . directories . included_directories . clone ( ) )
2022-04-23 07:46:33 +12:00
. group_by ( | _fe | ( ) )
. stop_receiver ( stop_receiver )
. progress_sender ( progress_sender )
2023-10-05 19:06:47 +13:00
. minimal_file_size ( self . common_data . minimal_file_size )
. maximal_file_size ( self . common_data . maximal_file_size )
. directories ( self . common_data . directories . clone ( ) )
. allowed_extensions ( self . common_data . allowed_extensions . clone ( ) )
. excluded_items ( self . common_data . excluded_items . clone ( ) )
. recursive_search ( self . common_data . recursive_search )
2022-04-23 07:46:33 +12:00
. build ( )
. run ( ) ;
2023-10-11 07:54:41 +13:00
match result {
2023-05-08 06:54:05 +12:00
DirTraversalResult ::SuccessFiles { grouped_file_entries , warnings } = > {
2023-10-11 07:54:41 +13:00
self . files_to_check = grouped_file_entries . into_values ( ) . flatten ( ) . collect ( ) ;
2023-10-05 19:06:47 +13:00
self . common_data . text_messages . warnings . extend ( warnings ) ;
2023-05-08 06:54:05 +12:00
2022-04-23 07:46:33 +12:00
true
}
DirTraversalResult ::SuccessFolders { .. } = > {
unreachable! ( )
}
DirTraversalResult ::Stopped = > false ,
2023-10-11 07:54:41 +13:00
}
2022-04-23 07:46:33 +12:00
}
2023-10-15 02:04:45 +13:00
#[ fun_time(message = " look_for_bad_extensions_files " , level = " debug " ) ]
2023-05-03 08:37:12 +12:00
fn look_for_bad_extensions_files ( & mut self , stop_receiver : Option < & Receiver < ( ) > > , progress_sender : Option < & UnboundedSender < ProgressData > > ) -> bool {
2023-05-08 06:54:05 +12:00
let ( progress_thread_handle , progress_thread_run , atomic_counter , check_was_stopped ) =
2023-10-05 19:06:47 +13:00
prepare_thread_handler_common ( progress_sender , 1 , 1 , self . files_to_check . len ( ) , CheckingMethod ::None , self . get_cd ( ) . tool_type ) ;
2022-04-23 07:46:33 +12:00
2023-05-08 06:54:05 +12:00
let files_to_check = mem ::take ( & mut self . files_to_check ) ;
2022-05-31 08:02:39 +12:00
2022-06-05 18:01:17 +12:00
let mut hashmap_workarounds : HashMap < & str , Vec < & str > > = Default ::default ( ) ;
2022-05-31 08:02:39 +12:00
for ( proper , found ) in WORKAROUNDS {
2023-05-03 08:37:12 +12:00
// This should be enabled when items will have only 1 possible workaround items, but looks that some have 2 or even more, so at least for now this is disabled
2022-06-05 18:01:17 +12:00
// if hashmap_workarounds.contains_key(found) {
// panic!("Already have {} key", found);
// }
2023-10-05 19:06:47 +13:00
hashmap_workarounds . entry ( found ) . or_default ( ) . push ( proper ) ;
2022-05-31 08:02:39 +12:00
}
2023-05-03 08:37:12 +12:00
self . bad_extensions_files = self . verify_extensions ( files_to_check , & atomic_counter , stop_receiver , & check_was_stopped , & hashmap_workarounds ) ;
send_info_and_wait_for_ending_all_threads ( & progress_thread_run , progress_thread_handle ) ;
// Break if stop was clicked
if check_was_stopped . load ( Ordering ::Relaxed ) {
return false ;
}
self . information . number_of_files_with_bad_extension = self . bad_extensions_files . len ( ) ;
2023-10-11 07:54:41 +13:00
debug! ( " Found {} files with invalid extension. " , self . information . number_of_files_with_bad_extension ) ;
2023-05-03 08:37:12 +12:00
true
}
2023-10-15 02:04:45 +13:00
#[ fun_time(message = " verify_extensions " , level = " debug " ) ]
2023-05-03 08:37:12 +12:00
fn verify_extensions (
& self ,
files_to_check : Vec < FileEntry > ,
atomic_counter : & Arc < AtomicUsize > ,
stop_receiver : Option < & Receiver < ( ) > > ,
check_was_stopped : & AtomicBool ,
hashmap_workarounds : & HashMap < & str , Vec < & str > > ,
) -> Vec < BadFileEntry > {
2023-10-11 07:54:41 +13:00
files_to_check
2022-05-31 08:02:39 +12:00
. into_par_iter ( )
2022-04-23 07:46:33 +12:00
. map ( | file_entry | {
2023-05-03 08:37:12 +12:00
atomic_counter . fetch_add ( 1 , Ordering ::Relaxed ) ;
2022-04-23 07:46:33 +12:00
if stop_receiver . is_some ( ) & & stop_receiver . unwrap ( ) . try_recv ( ) . is_ok ( ) {
2022-05-10 05:40:35 +12:00
check_was_stopped . store ( true , Ordering ::Relaxed ) ;
2022-04-23 07:46:33 +12:00
return None ;
}
// Check what exactly content file contains
let kind = match infer ::get_from_path ( & file_entry . path ) {
Ok ( k ) = > match k {
Some ( t ) = > t ,
None = > return Some ( None ) ,
} ,
Err ( _ ) = > return Some ( None ) ,
} ;
let proper_extension = kind . extension ( ) ;
2023-05-03 08:37:12 +12:00
let Some ( current_extension ) = self . get_and_validate_extension ( & file_entry , proper_extension ) else {
2022-04-23 07:46:33 +12:00
return Some ( None ) ;
2023-05-03 08:37:12 +12:00
} ;
2022-04-23 07:46:33 +12:00
// Check for all extensions that file can use(not sure if it is worth to do it)
2023-05-03 08:37:12 +12:00
let ( mut all_available_extensions , valid_extensions ) = self . check_for_all_extensions_that_file_can_use ( hashmap_workarounds , & current_extension , proper_extension ) ;
2022-04-23 07:46:33 +12:00
if all_available_extensions . is_empty ( ) {
// Not found any extension
return Some ( None ) ;
} else if current_extension . is_empty ( ) {
2023-05-03 08:37:12 +12:00
if ! self . include_files_without_extension {
2022-04-23 07:46:33 +12:00
return Some ( None ) ;
}
2023-05-03 08:37:12 +12:00
} else if all_available_extensions . take ( & current_extension ) . is_some ( ) {
2022-04-23 07:46:33 +12:00
// Found proper extension
return Some ( None ) ;
}
Some ( Some ( BadFileEntry {
path : file_entry . path ,
modified_date : file_entry . modified_date ,
size : file_entry . size ,
current_extension ,
2023-05-03 08:37:12 +12:00
proper_extensions : valid_extensions ,
2022-04-23 07:46:33 +12:00
} ) )
} )
. while_some ( )
2023-01-29 06:54:02 +13:00
. filter ( Option ::is_some )
. map ( Option ::unwrap )
2023-10-11 07:54:41 +13:00
. collect ::< Vec < _ > > ( )
2023-05-03 08:37:12 +12:00
}
2022-04-23 07:46:33 +12:00
2023-05-03 08:37:12 +12:00
fn get_and_validate_extension ( & self , file_entry : & FileEntry , proper_extension : & str ) -> Option < String > {
let current_extension ;
// Extract current extension from file
if let Some ( extension ) = file_entry . path . extension ( ) {
let extension = extension . to_string_lossy ( ) . to_lowercase ( ) ;
if DISABLED_EXTENSIONS . contains ( & extension . as_str ( ) ) {
return None ;
}
// Text longer than 10 characters is not considered as extension
if extension . len ( ) > 10 {
current_extension = String ::new ( ) ;
} else {
current_extension = extension ;
}
} else {
current_extension = String ::new ( ) ;
}
2022-04-23 07:46:33 +12:00
2023-05-03 08:37:12 +12:00
// Already have proper extension, no need to do more things
if current_extension = = proper_extension {
return None ;
2022-04-23 07:46:33 +12:00
}
2023-05-03 08:37:12 +12:00
Some ( current_extension )
}
2022-04-23 07:46:33 +12:00
2023-05-03 08:37:12 +12:00
fn check_for_all_extensions_that_file_can_use (
& self ,
hashmap_workarounds : & HashMap < & str , Vec < & str > > ,
current_extension : & str ,
proper_extension : & str ,
) -> ( BTreeSet < String > , String ) {
let mut all_available_extensions : BTreeSet < String > = Default ::default ( ) ;
let valid_extensions = if current_extension . is_empty ( ) {
String ::new ( )
} else {
for mim in mime_guess ::from_ext ( proper_extension ) {
if let Some ( all_ext ) = get_mime_extensions ( & mim ) {
for ext in all_ext {
all_available_extensions . insert ( ( * ext ) . to_string ( ) ) ;
}
}
}
2022-04-23 07:46:33 +12:00
2023-05-03 08:37:12 +12:00
// Workarounds
if let Some ( vec_pre ) = hashmap_workarounds . get ( current_extension ) {
for pre in vec_pre {
if all_available_extensions . contains ( * pre ) {
all_available_extensions . insert ( current_extension . to_string ( ) ) ;
break ;
}
}
}
2022-04-23 07:46:33 +12:00
2023-05-03 08:37:12 +12:00
let mut guessed_multiple_extensions = format! ( " ( {proper_extension} ) - " ) ;
for ext in & all_available_extensions {
guessed_multiple_extensions . push_str ( ext ) ;
guessed_multiple_extensions . push ( ',' ) ;
}
guessed_multiple_extensions . pop ( ) ;
2022-04-23 07:46:33 +12:00
2023-05-03 08:37:12 +12:00
guessed_multiple_extensions
} ;
( all_available_extensions , valid_extensions )
2022-04-23 07:46:33 +12:00
}
}
impl Default for BadExtensions {
fn default ( ) -> Self {
Self ::new ( )
}
}
impl DebugPrint for BadExtensions {
fn debug_print ( & self ) {
2023-10-11 07:54:41 +13:00
if ! cfg! ( debug_assertions ) {
2022-04-23 07:46:33 +12:00
return ;
}
println! ( " ---------------DEBUG PRINT--------------- " ) ;
2023-10-05 19:06:47 +13:00
self . debug_print_common ( ) ;
2022-04-23 07:46:33 +12:00
println! ( " ----------------------------------------- " ) ;
}
}
2023-10-11 07:54:41 +13:00
impl PrintResults for BadExtensions {
fn write_results < T : Write > ( & self , writer : & mut T ) -> std ::io ::Result < ( ) > {
writeln! (
2022-04-23 07:46:33 +12:00
writer ,
" Results of searching {:?} with excluded directories {:?} and excluded items {:?} " ,
2023-10-05 19:06:47 +13:00
self . common_data . directories . included_directories , self . common_data . directories . excluded_directories , self . common_data . excluded_items . items
2023-10-11 07:54:41 +13:00
) ? ;
writeln! ( writer , " Found {} files with invalid extension. \n " , self . information . number_of_files_with_bad_extension ) ? ;
2023-05-08 06:54:05 +12:00
2023-01-29 06:54:02 +13:00
for file_entry in & self . bad_extensions_files {
2023-10-11 07:54:41 +13:00
writeln! ( writer , " {} ----- {} " , file_entry . path . display ( ) , file_entry . proper_extensions ) ? ;
2022-04-23 07:46:33 +12:00
}
2023-10-11 07:54:41 +13:00
Ok ( ( ) )
2022-04-23 07:46:33 +12:00
}
2023-10-13 05:48:46 +13:00
fn save_results_to_file_as_json ( & self , file_name : & str , pretty_print : bool ) -> std ::io ::Result < ( ) > {
self . save_results_to_file_as_json_internal ( file_name , & self . bad_extensions_files , pretty_print )
}
2022-04-23 07:46:33 +12:00
}
2023-10-05 19:06:47 +13:00
impl BadExtensions {
pub const fn get_bad_extensions_files ( & self ) -> & Vec < BadFileEntry > {
& self . bad_extensions_files
}
pub const fn get_information ( & self ) -> & Info {
& self . information
}
}
impl CommonData for BadExtensions {
fn get_cd ( & self ) -> & CommonToolData {
& self . common_data
}
fn get_cd_mut ( & mut self ) -> & mut CommonToolData {
& mut self . common_data
}
}