1use std::fs::{ File, OpenOptions };
2use std::io::{BufReader,SeekFrom};
3use std::io::prelude::*;
4
5
6pub trait FileLoaderFile {
7 fn is_valid( &self ) -> bool;
8 fn read_u8( &mut self ) -> u8;
9 fn eof( &self ) -> bool;
10 fn name( &self ) -> &str;
11
12 fn read_u16( &mut self ) -> u16 {
13 let a = self.read_u8() as u16;
14 let b = self.read_u8() as u16;
15
16 ( b << 8 )
17 | ( a << 0 )
18 }
19
20 fn read_u32( &mut self ) -> u32 {
21 let a = self.read_u8() as u32;
22 let b = self.read_u8() as u32;
23 let c = self.read_u8() as u32;
24 let d = self.read_u8() as u32;
25
26 ( d << 24 )
27 | ( c << 16 )
28 | ( b << 8 )
29 | ( a << 0 )
30 }
31}
32
33
34pub trait FileLoader {
35 fn open( &mut self, filename: &str ) -> Box< dyn FileLoaderFile >;
36 fn exists( &self, filename: &str ) -> bool;
37}
38
39
40pub struct FileLoaderFileDisk {
41 filename: String, file: Option< BufReader< File > >,
43 size: usize,
44 pos: usize,
45}
46
47impl FileLoaderFileDisk {
48 pub fn open( filename: &str ) -> Self {
49 let mut s = Self {
50 filename: filename.to_string(),
51 file: None,
52 size: 0,
53 pos: 0,
54 };
55
56 if let Ok( mut f ) = File::open( &s.filename ) {
57 if let Ok( p ) = f.seek(SeekFrom::End(0)) {
58 f.seek( SeekFrom::Start( 0 ) ).unwrap();
59 s.size = p as usize
60 } else {
61 }
62 let f = BufReader::new(f);
63
64 s.file = Some( f );
65 };
66
67 s
68 }
69}
70
71impl FileLoaderFile for FileLoaderFileDisk {
72 fn read_u8( &mut self ) -> u8 {
73
74 match &mut self.file {
75 Some( f ) => {
76 let mut buf = [0];
77 match f.read( &mut buf ) {
78 Ok( _ ) => {
79 self.pos += 1;
80 buf[ 0 ]
81 },
82 Err( _ ) => 0,
83 }
84
85 },
86 None => {
87 0
88 },
89 }
90
91 }
92 fn is_valid( &self ) -> bool {
93 self.file.is_some()
94 }
95 fn eof( &self ) -> bool {
96 self.pos >= self.size
97 }
98 fn name( &self ) -> &str {
99 &self.filename
100 }
101}
102
103pub struct FileLoaderDisk {
104 basedir: String,
105 debug: bool,
106}
107
108impl FileLoaderDisk {
109 pub fn new( basedir: &str ) -> Self {
110 Self {
111 basedir: basedir.to_string(),
112 debug: false,
113 }
114 }
115 pub fn enable_debug ( &mut self ) {
116 self.debug = true;
117 }
118}
119
120impl FileLoader for FileLoaderDisk {
121 fn open( &mut self, filename: &str ) -> Box< dyn FileLoaderFile > {
122 let fullname = format!("{}/{}", &self.basedir, &filename);
123 if self.debug { println!("FileLoaderDisk opening {}", fullname); }
124 let stream = FileLoaderFileDisk::open( &fullname );
125
126 Box::new( stream )
127 }
128 fn exists( &self, filename: &str ) -> bool {
129 let fullname = format!("{}/{}", &self.basedir, &filename);
130 if self.debug { println!("FileLoaderDisk exists? {}", fullname); }
131 std::path::Path::new(&fullname).exists()
132 }
133
134
135}