Skip to content

RFC: Use byte slices directly in place of IoVec #263

Closed
@kamalmarhubi

Description

@kamalmarhubi

Summary

Make using pread et al nicer by getting rid of a special purpose struct and using a ubiquitous type instead.

Motivation

Using IoVec in nix is a little cumbersome. At present, in nix, the IoVec struct is defined:

pub struct IoVec<T> {
    iov_base: *mut c_void,
    iov_len: size_t,
    phantom: PhantomData<T>
}

The C struct iovec is defined:

struct iovec {
    void  *iov_base;            /* Starting address */
    size_t iov_len;             /* Number of bytes */
};

This is pretty much equivalent to &[u8]. See std::raw::Slice:

pub struct Slice<T> {
    pub data: *const T,
    pub len: usize,
}

However, the T type parameter is never used as anything other than [u8], and there is no way to even construct one with any other type.

Given that the C struct iovec is effectively a slice, and that it exists because C lacks slices, I propose we use slices in its place for the Rust interface.

Examples

Signatures before:

pub fn writev(fd: RawFd, iov: &[IoVec<&[u8]>]) -> Result<usize>;
pub fn readv(fd: RawFd, iov: &mut [IoVec<&mut [u8]>]) -> Result<usize>;

After:

pub fn writev(fd: RawFd, iov: &[&[u8]]) -> Result<usize>;
pub fn readv(fd: RawFd, iov: &mut [&mut [u8]]) -> Result<usize>;

If you want to see what it would look like, I've got a partial replacement here: kamalmarhubi@44825ba

The modified tests pass.

Drawbacks

We're relying on a semi-coincidental layout equivalence. This makes me a bit uneasy.

Alternatives

  • Leave it as is
  • Drop the type parameter, making IoVec only store byte slices.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions