@@ -49,10 +49,8 @@ pub struct DirBuilder {}
49
49
impl FileAttr {
50
50
/// Creates a FileAttr by getting data from an opened file.
51
51
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
+
56
54
if size >= 0 {
57
55
Ok ( Self { size : size as u64 } )
58
56
} else {
@@ -295,8 +293,83 @@ impl File {
295
293
Ok ( ( ) )
296
294
}
297
295
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 ( ) ?)
300
373
}
301
374
302
375
pub fn duplicate ( & self ) -> io:: Result < File > {
0 commit comments