twizzler_rt_abi/
io.rs

1//! Runtime interface for IO-like operations.
2
3#![allow(unused_variables)]
4use crate::{
5    error::RawTwzError,
6    fd::{RawFd, SocketAddress},
7    Result,
8};
9
10bitflags::bitflags! {
11    /// Possible flags for IO operations.
12    #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
13    pub struct IoFlags : crate::bindings::io_flags {
14        /// This operation should have non-blocking semantics, regardless of fd status.
15        const NONBLOCKING = crate::bindings::IO_NONBLOCKING;
16    }
17}
18
19/// Possible seek start points and offset.
20pub enum SeekFrom {
21    Start(u64),
22    End(i64),
23    Current(i64),
24}
25
26fn optoff(off: Option<u64>) -> crate::bindings::optional_offset {
27    match off {
28        Some(o) => o.try_into().unwrap_or(crate::bindings::FD_POS),
29        None => crate::bindings::FD_POS,
30    }
31}
32
33impl Into<Result<usize>> for crate::bindings::io_result {
34    fn into(self) -> Result<usize> {
35        let raw = RawTwzError::new(self.err);
36        if raw.is_success() {
37            Ok(self.val)
38        } else {
39            Err(raw.error())
40        }
41    }
42}
43
44impl From<Result<usize>> for crate::bindings::io_result {
45    fn from(value: Result<usize>) -> Self {
46        match value {
47            Ok(v) => Self {
48                val: v,
49                err: RawTwzError::success().raw(),
50            },
51            Err(e) => Self {
52                val: 0,
53                err: e.raw(),
54            },
55        }
56    }
57}
58
59#[derive(Clone, Copy)]
60#[repr(transparent)]
61pub struct IoCtx(crate::bindings::io_ctx);
62
63impl Default for IoCtx {
64    fn default() -> Self {
65        Self::new(None, IoFlags::empty(), None)
66    }
67}
68
69impl IoCtx {
70    pub fn new(pos: Option<u64>, flags: IoFlags, timeout: Option<core::time::Duration>) -> Self {
71        Self(crate::bindings::io_ctx {
72            offset: optoff(pos),
73            flags: flags.bits(),
74            timeout: timeout.into(),
75        })
76    }
77
78    pub fn offset(mut self, offset: Option<u64>) -> Self {
79        self.0.offset = optoff(offset);
80        self
81    }
82
83    pub fn flags(mut self, flags: IoFlags) -> Self {
84        self.0.flags = flags.bits();
85        self
86    }
87
88    pub fn timeout(mut self, timeout: Option<core::time::Duration>) -> Self {
89        self.0.timeout = timeout.into();
90        self
91    }
92}
93
94/// Read a file descriptor into a buffer, up to buf.len() bytes. On success, returns the number of
95/// bytes actually read, which may be fewer than requested.
96pub fn twz_rt_fd_pread(fd: RawFd, buf: &mut [u8], ctx: &mut IoCtx) -> Result<usize> {
97    unsafe {
98        crate::bindings::twz_rt_fd_pread(fd, buf.as_mut_ptr().cast(), buf.len(), &mut ctx.0).into()
99    }
100}
101
102/// Write bytes from a buffer into a file descriptor, up to buf.len() bytes. On success, returns the
103/// number of bytes actually written, which may be fewer than requested.
104pub fn twz_rt_fd_pwrite(fd: RawFd, buf: &[u8], ctx: &mut IoCtx) -> Result<usize> {
105    unsafe {
106        crate::bindings::twz_rt_fd_pwrite(fd, buf.as_ptr().cast(), buf.len(), &mut ctx.0).into()
107    }
108}
109
110/// Seek a file descriptor, changing the internal position.
111pub fn twz_rt_fd_seek(fd: RawFd, seek: SeekFrom) -> Result<usize> {
112    let (whence, off) = match seek {
113        SeekFrom::Start(s) => (crate::bindings::WHENCE_START, s as i64),
114        SeekFrom::End(s) => (crate::bindings::WHENCE_END, s),
115        SeekFrom::Current(s) => (crate::bindings::WHENCE_CURRENT, s),
116    };
117    unsafe { crate::bindings::twz_rt_fd_seek(fd, whence, off).into() }
118}
119
120#[derive(Copy, Clone)]
121#[repr(transparent)]
122pub struct Endpoint(crate::bindings::endpoint);
123
124impl Endpoint {
125    fn new_socket(sock: super::fd::SocketAddress) -> Self {
126        Self(crate::bindings::endpoint {
127            kind: crate::bindings::endpoint_kind_Endpoint_Socket,
128            addr: crate::bindings::endpoint_addrs {
129                socket_addr: sock.0,
130            },
131        })
132    }
133}
134
135#[repr(u32)]
136pub enum EndpointKind {
137    Unspecified = crate::bindings::endpoint_kind_Endpoint_Unspecified,
138    Socket = crate::bindings::endpoint_kind_Endpoint_Socket,
139}
140
141impl From<crate::bindings::endpoint> for Endpoint {
142    fn from(value: crate::bindings::endpoint) -> Self {
143        Self(value)
144    }
145}
146
147impl From<SocketAddress> for Endpoint {
148    fn from(value: SocketAddress) -> Self {
149        Self::new_socket(value)
150    }
151}
152
153/// Read a file descriptor into a buffer, up to buf.len() bytes. On success, returns the number of
154/// bytes actually read, which may be fewer than requested.
155pub fn twz_rt_fd_pread_from(
156    fd: RawFd,
157    buf: &mut [u8],
158    ctx: &mut IoCtx,
159) -> Result<(usize, Endpoint)> {
160    let mut endpoint = core::mem::MaybeUninit::uninit();
161    unsafe {
162        let len: Result<_> = crate::bindings::twz_rt_fd_pread_from(
163            fd,
164            buf.as_mut_ptr().cast(),
165            buf.len(),
166            &mut ctx.0,
167            endpoint.as_mut_ptr(),
168        )
169        .into();
170        let len = len?;
171        Ok((len, endpoint.assume_init().into()))
172    }
173}
174
175/// Write bytes from a buffer into a file descriptor, up to buf.len() bytes. On success, returns the
176/// number of bytes actually written, which may be fewer than requested.
177pub fn twz_rt_fd_pwrite_to(
178    fd: RawFd,
179    buf: &[u8],
180    ctx: &mut IoCtx,
181    mut ep: Endpoint,
182) -> Result<usize> {
183    unsafe {
184        crate::bindings::twz_rt_fd_pwrite_to(
185            fd,
186            buf.as_ptr().cast(),
187            buf.len(),
188            &mut ctx.0,
189            &mut ep.0,
190        )
191        .into()
192    }
193}
194
195/// Type of an IO vec buffer and length.
196pub type IoSlice = crate::bindings::io_vec;
197
198/// Read a file descriptor into a multiple buffers. On success, returns the number of bytes actually
199/// read, which may be fewer than requested. If offset is None, use the file descriptor's internal
200/// position. If the file descriptor refers to a non-seekable file, and offset is Some, this
201/// function returns an error.
202pub fn twz_rt_fd_preadv(fd: RawFd, ios: &[IoSlice], ctx: &mut IoCtx) -> Result<usize> {
203    unsafe { crate::bindings::twz_rt_fd_pwritev(fd, ios.as_ptr(), ios.len(), &mut ctx.0).into() }
204}
205
206/// Write multiple buffers into a file descriptor. On success, returns the number of bytes actually
207/// written, which may be fewer than requested. If offset is None, use the file descriptor's
208/// internal position. If the file descriptor refers to a non-seekable file, and offset is Some,
209/// this function returns an error.
210pub fn twz_rt_fd_pwritev(fd: RawFd, ios: &[IoSlice], ctx: &mut IoCtx) -> Result<usize> {
211    unsafe { crate::bindings::twz_rt_fd_pwritev(fd, ios.as_ptr(), ios.len(), &mut ctx.0).into() }
212}