@@ -49,10 +49,8 @@ pub struct DirBuilder {}
4949impl FileAttr {
5050 /// Creates a FileAttr by getting data from an opened file.
5151 fn from_fd ( fd : * mut vex_sdk:: FIL ) -> io:: Result < Self > {
52- let size = unsafe {
53- vex_sdk:: vexFileSize ( fd)
54- } ;
55-
52+ let size = unsafe { vex_sdk:: vexFileSize ( fd) } ;
53+
5654 if size >= 0 {
5755 Ok ( Self { size : size as u64 } )
5856 } else {
@@ -295,8 +293,83 @@ impl File {
295293 Ok ( ( ) )
296294 }
297295
298- pub fn seek ( & self , _pos : SeekFrom ) -> io:: Result < u64 > {
299- todo ! ( ) ;
296+ fn tell ( & self ) -> io:: Result < u64 > {
297+ let position = unsafe { vex_sdk:: vexFileTell ( self . fd . 0 ) } ;
298+ position. try_into ( ) . map_err ( |_| {
299+ io:: Error :: new ( io:: ErrorKind :: InvalidData , "Failed to get current location in file" )
300+ } )
301+ }
302+
303+ pub fn seek ( & self , pos : SeekFrom ) -> io:: Result < u64 > {
304+ const SEEK_SET : i32 = 0 ;
305+ const SEEK_CUR : i32 = 1 ;
306+ const SEEK_END : i32 = 2 ;
307+
308+ fn try_convert_offset < T : TryInto < u32 > > ( offset : T ) -> io:: Result < u32 > {
309+ offset. try_into ( ) . map_err ( |_| {
310+ io:: Error :: new (
311+ io:: ErrorKind :: InvalidInput ,
312+ "Cannot seek to an offset too large to fit in a 32 bit integer" ,
313+ )
314+ } )
315+ }
316+
317+ match pos {
318+ SeekFrom :: Start ( offset) => unsafe {
319+ map_fresult ( vex_sdk:: vexFileSeek ( self . fd . 0 , try_convert_offset ( offset) ?, SEEK_SET ) ) ?
320+ } ,
321+
322+ // The VEX SDK does not allow seeking with negative offsets.
323+ // That means we need to calculate the offset from the start for both of these.
324+ SeekFrom :: End ( offset) => unsafe {
325+ // If our offset is positive, everything is easy
326+ if offset >= 0 {
327+ map_fresult ( vex_sdk:: vexFileSeek (
328+ self . fd . 0 ,
329+ try_convert_offset ( offset) ?,
330+ SEEK_END ,
331+ ) ) ?
332+ } else {
333+ // Get the position of the end of the file...
334+ map_fresult ( vex_sdk:: vexFileSeek (
335+ self . fd . 0 ,
336+ try_convert_offset ( offset) ?,
337+ SEEK_END ,
338+ ) ) ?;
339+ // The number returned by the VEX SDK tell is stored as a 32 bit interger,
340+ // and therefore this conversion cannot fail.
341+ let position = self . tell ( ) ? as i64 ;
342+
343+ // Offset from that position
344+ let new_position = position + offset;
345+ map_fresult ( vex_sdk:: vexFileSeek (
346+ self . fd . 0 ,
347+ try_convert_offset ( new_position) ?,
348+ SEEK_SET ,
349+ ) ) ?
350+ }
351+ } ,
352+ SeekFrom :: Current ( offset) => unsafe {
353+ if offset >= 0 {
354+ map_fresult ( vex_sdk:: vexFileSeek (
355+ self . fd . 0 ,
356+ try_convert_offset ( offset) ?,
357+ SEEK_CUR ,
358+ ) ) ?
359+ } else {
360+ let position = self . tell ( ) ? as i64 ;
361+
362+ let new_position = position + offset;
363+ map_fresult ( vex_sdk:: vexFileSeek (
364+ self . fd . 0 ,
365+ try_convert_offset ( new_position) ?,
366+ SEEK_SET ,
367+ ) ) ?
368+ }
369+ } ,
370+ }
371+
372+ Ok ( self . tell ( ) ?)
300373 }
301374
302375 pub fn duplicate ( & self ) -> io:: Result < File > {
0 commit comments