Skip to content

Commit c0cc793

Browse files
Gavin-Niedermanmax-niederman
authored andcommitted
feat: seek implementation
1 parent b0c536b commit c0cc793

File tree

1 file changed

+79
-6
lines changed
  • library/std/src/sys/pal/vexos

1 file changed

+79
-6
lines changed

library/std/src/sys/pal/vexos/fs.rs

Lines changed: 79 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,8 @@ pub struct DirBuilder {}
4949
impl 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

Comments
 (0)