@@ -6,9 +6,12 @@ use crate::path::{Path, PathBuf};
66use crate :: sys:: time:: SystemTime ;
77use crate :: sys:: unsupported;
88
9+ #[ derive( Debug ) ]
910struct FileDesc ( * mut vex_sdk:: FIL ) ;
1011
11- pub struct File ( FileDesc ) ;
12+ pub struct File {
13+ fd : FileDesc ,
14+ }
1215
1316//TODO: We may be able to get some of this info
1417#[ derive( Clone ) ]
@@ -149,12 +152,8 @@ impl OpenOptions {
149152
150153impl File {
151154 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 ( ) } ) ?;
158157
159158 let path = CString :: new ( path. as_os_str ( ) . as_encoded_bytes ( ) ) . map_err ( |_| {
160159 io:: Error :: new ( io:: ErrorKind :: InvalidData , "Path contained a null byte" )
@@ -180,7 +179,7 @@ impl File {
180179 if file. is_null ( ) {
181180 Err ( io:: Error :: new ( io:: ErrorKind :: NotFound , "Could not open file" ) )
182181 } else {
183- Ok ( Self ( FileDesc ( file) ) )
182+ Ok ( Self { fd : FileDesc ( file) } )
184183 }
185184 }
186185
@@ -203,7 +202,7 @@ impl File {
203202 pub fn read ( & self , buf : & mut [ u8 ] ) -> io:: Result < usize > {
204203 let len = buf. len ( ) as _ ;
205204 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 ) } ;
207206 if read < 0 {
208207 Err ( io:: Error :: new ( io:: ErrorKind :: Other , "Could not read from file" ) )
209208 } else {
@@ -227,12 +226,10 @@ impl File {
227226 pub fn write ( & self , buf : & [ u8 ] ) -> io:: Result < usize > {
228227 let len = buf. len ( ) ;
229228 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 ) } ;
231231 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" ) )
236233 } else {
237234 Ok ( written as usize )
238235 }
@@ -249,7 +246,7 @@ impl File {
249246
250247 pub fn flush ( & self ) -> io:: Result < ( ) > {
251248 unsafe {
252- vex_sdk:: vexFileSync ( self . 0 . 0 ) ;
249+ vex_sdk:: vexFileSync ( self . fd . 0 ) ;
253250 }
254251 Ok ( ( ) )
255252 }
@@ -259,7 +256,7 @@ impl File {
259256 }
260257
261258 pub fn duplicate ( & self ) -> io:: Result < File > {
262- unsupported ! ( )
259+ unsupported ( )
263260 }
264261
265262 pub fn set_permissions ( & self , _perm : FilePermissions ) -> io:: Result < ( ) > {
@@ -283,17 +280,17 @@ impl DirBuilder {
283280
284281impl fmt:: Debug for File {
285282 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 ( )
287284 }
288285}
289286impl Drop for File {
290287 fn drop ( & mut self ) {
291- unsafe { vex_sdk:: vexFileClose ( self . 0 . 0 ) } ;
288+ unsafe { vex_sdk:: vexFileClose ( self . fd . 0 ) } ;
292289 }
293290}
294291
295292pub fn readdir ( _p : & Path ) -> io:: Result < ReadDir > {
296- unsupported ( )
293+ todo ! ( )
297294}
298295
299296pub fn unlink ( _p : & Path ) -> io:: Result < ( ) > {
@@ -317,7 +314,7 @@ pub fn remove_dir_all(_path: &Path) -> io::Result<()> {
317314}
318315
319316pub fn try_exists ( _path : & Path ) -> io:: Result < bool > {
320- unsupported ( )
317+ todo ! ( )
321318}
322319
323320pub fn readlink ( _p : & Path ) -> io:: Result < PathBuf > {
@@ -333,7 +330,7 @@ pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> {
333330}
334331
335332pub fn stat ( _p : & Path ) -> io:: Result < FileAttr > {
336- unsupported ( )
333+ todo ! ( )
337334}
338335
339336pub fn lstat ( _p : & Path ) -> io:: Result < FileAttr > {
@@ -344,6 +341,95 @@ pub fn canonicalize(_p: &Path) -> io::Result<PathBuf> {
344341 unsupported ( )
345342}
346343
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+ }
349435}
0 commit comments