Skip to content

Figure out the future of nix #190

Open
@carllerche

Description

@carllerche

tl;dr Should nix be split up into multiple crates named nix-* and what should the API style be?

The situation

Nix originated as a posix binding dumping ground for various crates that I had been working on. I tended to need the same bindings over and over again, so I just moved them into Nix. I thought this would be useful for other people, so I accepted PRs for various system APIs as they have been submitted.

Everything has been fine so far, but a few issues have arisen.

As the API coverage has increased, whenever a breaking change is made, the semver must be incremented. So, if the ioctl module changes an API as it figures out the best way to expose functionality, the version must be bumped and downstream crates must change their dependencies. For example, Mio depends on nix, but not on any ioctl features, so bumping the dependency is pretty annoying.

Secondly, the API style has been somewhat ad hoc, especially with more complicated system APIs like fcntl.

Crate structure

There is value in having a single place (nix) to find system APIs that have a coherent API style and a single documentation site. I think that each specific API silo, like sockets, ioctl, mqueue, signals, etc... could be in their own crate named nix_*. Common features like errors, NixPath, etc... would live in nix_core. The nix crate would be a facade depending on all the sub crates with liberal dependencies (probably "*") which would allow the consumer to optionally be able to pin each sub crate to whatever.

Libraries like Mio could then depend only on the features that are needed.

Also, it would allow delegating responsibility better. I, for one, know nothing about ioctl. I would like to stop being the blocker.

API style

This is still something that I haven't figured out. I do know that the goal of nix is *comprehensive, safe, zero cost bindings to system APIs on nix OSes.

So, what does that mean for nix? As of now, there are currently a variety of styles. For example, most APIs are 1-1 bindings to the equivalent OS api. This leads to APIs like fcntl which uses a convoluted FcntlArg strategy. ioctl on the other hand uses a (fairly impressive) macro...

The question is, would it be better to expand beyond the 1-1 rule. For example, in the fnctl case, the API would most likely be much cleaner and more "rusty" if each "fcntl arg" was moved to an individual function. There could, for example, be a public fcntl mod with a dupfd function. Using it would be:

let res = fcntl::dup_fd(fd);

Then, should it go further? Should there be an Fd type that wraps std::os::unix::RawFd and implement functions like dup directly on that type?

These are all open questions that I pose to the users of nix.

cc @posborne @cmr @geofft @utkarshkukreti @MarkusJais and whoever else :)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions