use core::slice;
use drone_core::ffi::{c_char, c_int, c_uint, c_void};
use drone_core::io::SeekFrom;
use drone_micropython_raw::{
mp_import_stat_t, off_t, EINVAL, SEEK_CUR, SEEK_END, SEEK_SET,
};
use io::{Fd, Flags, IoReq, IoReqRes};
use rt::MP_ERRNO;
pub trait IoRt {
fn req(req: IoReq) -> IoReqRes;
#[doc(hidden)]
#[inline(always)]
unsafe fn open(path: *const c_char, flags: c_char) -> c_int {
let flags = Flags::new(flags);
match Self::req(IoReq::Open { path, flags }).open {
Ok(fd) => fd.to_c_int(),
Err(err) => {
MP_ERRNO = err;
-1
}
}
}
#[doc(hidden)]
#[inline(always)]
unsafe fn read(fd: c_int, buf: *mut c_void, count: usize) -> isize {
let fd = Fd::new(fd);
let buf = slice::from_raw_parts_mut(buf as *mut u8, count);
match Self::req(IoReq::Read { fd, buf }).read {
Ok(n) => n as isize,
Err(err) => {
MP_ERRNO = err;
-1
}
}
}
#[doc(hidden)]
#[inline(always)]
unsafe fn write(fd: c_int, buf: *const c_void, count: usize) -> isize {
let fd = Fd::new(fd);
let buf = slice::from_raw_parts(buf as *const u8, count);
match Self::req(IoReq::Write { fd, buf }).write {
Ok(n) => n as isize,
Err(err) => {
MP_ERRNO = err;
-1
}
}
}
#[doc(hidden)]
#[inline(always)]
unsafe fn lseek(fd: c_int, offset: off_t, whence: c_int) -> off_t {
let fd = Fd::new(fd);
let pos = match whence as c_uint {
SEEK_SET => SeekFrom::Start(offset as u64),
SEEK_CUR => SeekFrom::Current(i64::from(offset)),
SEEK_END => SeekFrom::End(i64::from(offset)),
_ => {
MP_ERRNO = EINVAL as c_int;
return -1;
}
};
match Self::req(IoReq::Seek { fd, pos }).seek {
Ok(off) => off as off_t,
Err(err) => {
MP_ERRNO = err;
-1
}
}
}
#[doc(hidden)]
#[inline(always)]
unsafe fn fsync(fd: c_int) -> c_int {
let fd = Fd::new(fd);
match Self::req(IoReq::Fsync { fd }).fsync {
Ok(()) => 0,
Err(err) => {
MP_ERRNO = err;
-1
}
}
}
#[doc(hidden)]
#[inline(always)]
unsafe fn close(fd: c_int) -> c_int {
let fd = Fd::new(fd);
match Self::req(IoReq::Close { fd }).close {
Ok(()) => 0,
Err(err) => {
MP_ERRNO = err;
-1
}
}
}
#[doc(hidden)]
#[inline(always)]
unsafe fn mp_import_stat(path: *const c_char) -> mp_import_stat_t {
match Self::req(IoReq::ImportStat { path }).import_stat {
Ok(import_stat) => import_stat,
Err(_) => mp_import_stat_t::MP_IMPORT_STAT_NO_EXIST,
}
}
}