@@ -6,9 +6,12 @@ use crate::path::{Path, PathBuf};
6
6
use crate :: sys:: time:: SystemTime ;
7
7
use crate :: sys:: unsupported;
8
8
9
+ #[ derive( Debug ) ]
9
10
struct FileDesc ( * mut vex_sdk:: FIL ) ;
10
11
11
- pub struct File ( FileDesc ) ;
12
+ pub struct File {
13
+ fd : FileDesc ,
14
+ }
12
15
13
16
//TODO: We may be able to get some of this info
14
17
#[ derive( Clone ) ]
@@ -149,12 +152,8 @@ impl OpenOptions {
149
152
150
153
impl File {
151
154
pub fn open ( path : & Path , opts : & OpenOptions ) -> io:: Result < File > {
152
- let fs_status = unsafe { vex_sdk:: vexFileMountSD ( ) } ;
153
- match fs_status {
154
- vex_sdk:: FRESULT :: FR_OK => ( ) ,
155
- //TODO: cover more results
156
- _ => return Err ( io:: Error :: new ( io:: ErrorKind :: NotFound , "SD card cannot be written or read from" ) ) ,
157
- }
155
+ // Mount sdcard volume as FAT filesystem
156
+ map_fresult ( unsafe { vex_sdk:: vexFileMountSD ( ) } ) ?;
158
157
159
158
let path = CString :: new ( path. as_os_str ( ) . as_encoded_bytes ( ) ) . map_err ( |_| {
160
159
io:: Error :: new ( io:: ErrorKind :: InvalidData , "Path contained a null byte" )
@@ -180,7 +179,7 @@ impl File {
180
179
if file. is_null ( ) {
181
180
Err ( io:: Error :: new ( io:: ErrorKind :: NotFound , "Could not open file" ) )
182
181
} else {
183
- Ok ( Self ( FileDesc ( file) ) )
182
+ Ok ( Self { fd : FileDesc ( file) } )
184
183
}
185
184
}
186
185
@@ -203,7 +202,7 @@ impl File {
203
202
pub fn read ( & self , buf : & mut [ u8 ] ) -> io:: Result < usize > {
204
203
let len = buf. len ( ) as _ ;
205
204
let buf_ptr = buf. as_mut_ptr ( ) ;
206
- let read = unsafe { vex_sdk:: vexFileRead ( buf_ptr. cast ( ) , 1 , len, self . 0 . 0 ) } ;
205
+ let read = unsafe { vex_sdk:: vexFileRead ( buf_ptr. cast ( ) , 1 , len, self . fd . 0 ) } ;
207
206
if read < 0 {
208
207
Err ( io:: Error :: new ( io:: ErrorKind :: Other , "Could not read from file" ) )
209
208
} else {
@@ -227,12 +226,10 @@ impl File {
227
226
pub fn write ( & self , buf : & [ u8 ] ) -> io:: Result < usize > {
228
227
let len = buf. len ( ) ;
229
228
let buf_ptr = buf. as_ptr ( ) ;
230
- let written = unsafe { vex_sdk:: vexFileWrite ( buf_ptr. cast_mut ( ) . cast ( ) , 1 , len as _ , self . 0 . 0 ) } ;
229
+ let written =
230
+ unsafe { vex_sdk:: vexFileWrite ( buf_ptr. cast_mut ( ) . cast ( ) , 1 , len as _ , self . fd . 0 ) } ;
231
231
if written < 0 {
232
- Err ( io:: Error :: new (
233
- io:: ErrorKind :: Other ,
234
- "Could not write to file" ,
235
- ) )
232
+ Err ( io:: Error :: new ( io:: ErrorKind :: Other , "Could not write to file" ) )
236
233
} else {
237
234
Ok ( written as usize )
238
235
}
@@ -249,7 +246,7 @@ impl File {
249
246
250
247
pub fn flush ( & self ) -> io:: Result < ( ) > {
251
248
unsafe {
252
- vex_sdk:: vexFileSync ( self . 0 . 0 ) ;
249
+ vex_sdk:: vexFileSync ( self . fd . 0 ) ;
253
250
}
254
251
Ok ( ( ) )
255
252
}
@@ -259,7 +256,7 @@ impl File {
259
256
}
260
257
261
258
pub fn duplicate ( & self ) -> io:: Result < File > {
262
- unsupported ! ( )
259
+ unsupported ( )
263
260
}
264
261
265
262
pub fn set_permissions ( & self , _perm : FilePermissions ) -> io:: Result < ( ) > {
@@ -283,17 +280,17 @@ impl DirBuilder {
283
280
284
281
impl fmt:: Debug for File {
285
282
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
286
- f. debug_struct ( "File" ) . finish_non_exhaustive ( )
283
+ f. debug_struct ( "File" ) . field ( "fd" , & self . fd . 0 ) . finish ( )
287
284
}
288
285
}
289
286
impl Drop for File {
290
287
fn drop ( & mut self ) {
291
- unsafe { vex_sdk:: vexFileClose ( self . 0 . 0 ) } ;
288
+ unsafe { vex_sdk:: vexFileClose ( self . fd . 0 ) } ;
292
289
}
293
290
}
294
291
295
292
pub fn readdir ( _p : & Path ) -> io:: Result < ReadDir > {
296
- unsupported ( )
293
+ todo ! ( )
297
294
}
298
295
299
296
pub fn unlink ( _p : & Path ) -> io:: Result < ( ) > {
@@ -317,7 +314,7 @@ pub fn remove_dir_all(_path: &Path) -> io::Result<()> {
317
314
}
318
315
319
316
pub fn try_exists ( _path : & Path ) -> io:: Result < bool > {
320
- unsupported ( )
317
+ todo ! ( )
321
318
}
322
319
323
320
pub fn readlink ( _p : & Path ) -> io:: Result < PathBuf > {
@@ -333,7 +330,7 @@ pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> {
333
330
}
334
331
335
332
pub fn stat ( _p : & Path ) -> io:: Result < FileAttr > {
336
- unsupported ( )
333
+ todo ! ( )
337
334
}
338
335
339
336
pub fn lstat ( _p : & Path ) -> io:: Result < FileAttr > {
@@ -344,6 +341,95 @@ pub fn canonicalize(_p: &Path) -> io::Result<PathBuf> {
344
341
unsupported ( )
345
342
}
346
343
347
- pub fn copy ( _from : & Path , _to : & Path ) -> io:: Result < u64 > {
348
- unsupported ( )
344
+ pub fn copy ( from : & Path , to : & Path ) -> io:: Result < u64 > {
345
+ use crate :: fs:: File ;
346
+
347
+ let mut reader = File :: open ( from) ?;
348
+ let mut writer = File :: create ( to) ?;
349
+
350
+ io:: copy ( & mut reader, & mut writer)
351
+ }
352
+
353
+ fn map_fresult ( fresult : vex_sdk:: FRESULT ) -> io:: Result < ( ) > {
354
+ // VEX presumably uses a derivative of FatFs (most likely the xilffs library)
355
+ // for sdcard filesystem functions.
356
+ //
357
+ // Documentation for each FRESULT originates from here:
358
+ // <http://elm-chan.org/fsw/ff/doc/rc.html>
359
+ match fresult {
360
+ vex_sdk:: FRESULT :: FR_OK => Ok ( ( ) ) ,
361
+ vex_sdk:: FRESULT :: FR_DISK_ERR => Err ( io:: Error :: new (
362
+ io:: ErrorKind :: Uncategorized ,
363
+ "internal function reported an unrecoverable hard error" ,
364
+ ) ) ,
365
+ vex_sdk:: FRESULT :: FR_INT_ERR => Err ( io:: Error :: new (
366
+ io:: ErrorKind :: Uncategorized ,
367
+ "assertion failed and an insanity is detected in the internal process" ,
368
+ ) ) ,
369
+ vex_sdk:: FRESULT :: FR_NOT_READY => Err ( io:: Error :: new (
370
+ io:: ErrorKind :: Uncategorized ,
371
+ "the storage device could not be prepared to work" ,
372
+ ) ) ,
373
+ vex_sdk:: FRESULT :: FR_NO_FILE => {
374
+ Err ( io:: Error :: new ( io:: ErrorKind :: NotFound , "could not find the file in the directory" ) )
375
+ }
376
+ vex_sdk:: FRESULT :: FR_NO_PATH => Err ( io:: Error :: new (
377
+ io:: ErrorKind :: NotFound ,
378
+ "a directory in the path name could not be found" ,
379
+ ) ) ,
380
+ vex_sdk:: FRESULT :: FR_INVALID_NAME => Err ( io:: Error :: new (
381
+ io:: ErrorKind :: InvalidInput ,
382
+ "the given string is invalid as a path name" ,
383
+ ) ) ,
384
+ vex_sdk:: FRESULT :: FR_DENIED => Err ( io:: Error :: new (
385
+ io:: ErrorKind :: PermissionDenied ,
386
+ "the required access for this operation was denied" ,
387
+ ) ) ,
388
+ vex_sdk:: FRESULT :: FR_EXIST => Err ( io:: Error :: new (
389
+ io:: ErrorKind :: AlreadyExists ,
390
+ "an object with the same name already exists in the directory" ,
391
+ ) ) ,
392
+ vex_sdk:: FRESULT :: FR_INVALID_OBJECT => Err ( io:: Error :: new (
393
+ io:: ErrorKind :: Uncategorized ,
394
+ "invalid or null file/directory object" ,
395
+ ) ) ,
396
+ vex_sdk:: FRESULT :: FR_WRITE_PROTECTED => Err ( io:: Error :: new (
397
+ io:: ErrorKind :: PermissionDenied ,
398
+ "a write operation was performed on write-protected media" ,
399
+ ) ) ,
400
+ vex_sdk:: FRESULT :: FR_INVALID_DRIVE => Err ( io:: Error :: new (
401
+ io:: ErrorKind :: InvalidInput ,
402
+ "an invalid drive number was specified in the path name" ,
403
+ ) ) ,
404
+ vex_sdk:: FRESULT :: FR_NOT_ENABLED => Err ( io:: Error :: new (
405
+ io:: ErrorKind :: Uncategorized ,
406
+ "work area for the logical drive has not been registered" ,
407
+ ) ) ,
408
+ vex_sdk:: FRESULT :: FR_NO_FILESYSTEM => Err ( io:: Error :: new (
409
+ io:: ErrorKind :: Uncategorized ,
410
+ "valid FAT volume could not be found on the drive" ,
411
+ ) ) ,
412
+ vex_sdk:: FRESULT :: FR_MKFS_ABORTED => {
413
+ Err ( io:: Error :: new ( io:: ErrorKind :: Uncategorized , "failed to create filesystem volume" ) )
414
+ }
415
+ vex_sdk:: FRESULT :: FR_TIMEOUT => Err ( io:: Error :: new (
416
+ io:: ErrorKind :: TimedOut ,
417
+ "the function was canceled due to a timeout of thread-safe control" ,
418
+ ) ) ,
419
+ vex_sdk:: FRESULT :: FR_LOCKED => Err ( io:: Error :: new (
420
+ io:: ErrorKind :: Uncategorized ,
421
+ "the operation to the object was rejected by file sharing control" ,
422
+ ) ) ,
423
+ vex_sdk:: FRESULT :: FR_NOT_ENOUGH_CORE => {
424
+ Err ( io:: Error :: new ( io:: ErrorKind :: OutOfMemory , "not enough memory for the operation" ) )
425
+ }
426
+ vex_sdk:: FRESULT :: FR_TOO_MANY_OPEN_FILES => Err ( io:: Error :: new (
427
+ io:: ErrorKind :: Uncategorized ,
428
+ "maximum number of open files has been reached" ,
429
+ ) ) ,
430
+ vex_sdk:: FRESULT :: FR_INVALID_PARAMETER => {
431
+ Err ( io:: Error :: new ( io:: ErrorKind :: InvalidInput , "a given parameter was invalid" ) )
432
+ }
433
+ _ => unreachable ! ( ) , // C-style enum
434
+ }
349
435
}
0 commit comments