-
Notifications
You must be signed in to change notification settings - Fork 676
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Revisit passing of strings: redesign and replace NixPath #221
Comments
We should basically just use struct NixPath([u8; MAX_PATH]);
impl NixPath {
fn new<T: AsRef<[u8]>>(t: T) -> Result<Self> { ... }
}
impl AsRef<CStr> for NixPath { ... } |
The stack usage gave me a lot of confusion with "disappearing" strings! (This was "my fault" for returning the result of
Using |
Mm, that's the purpose of using the closure. It's not a rare Rust idiom, but shouldn't really be used unless strictly necessary. Lifetimes would normally catch that sort of misuse, but oop pointers!
Yeah as soon as I realised that I submitted rust-lang/rust#30616 because that's a huge missing trait impl for libstd. It's silly, it basically means we're stuck with using our own trait instead that's just a clone of Alternatively, the trait could look more like so: trait ToCStr {
type Target: AsRef<CStr>;
fn to_cstr(&self) -> Result<Self::Target> { ... }
} ... which would retain the current behaviour of being able to pass OsStrs, Paths, etc. without the closure weirdness. I'm personally not a fan of the hidden conversions though, it feels a bit too magical for a Rust API vs just using |
Yeah! Working on
This sounds like a good plan.
Assuming this was the desired path, would
I see where this is coming from. Rust definitely favours explicitness! In #190, @carllerche's stated goal of nix is "*I do know that the goal of nix is comprehensive, safe, zero cost bindings to system APIs on nix OSes", so your feelings are in line with that. |
Given the direction of discussion here, I'm changing the title of the issue :-) |
One additional niggle of using |
Yeah, that's a pain... For the most part, the advantage of |
In fact, until
The difference is that
I think it makes for a cleaner API, @carllerche: opinions? |
Yeah, as one of my multiple attempts at a semi-ergonomic
It didn't work. |
Especially for the
This comes back to functions that allow |
Yes, that's exactly what |
My justification for the existing (commented out) set of
Still, requiring careful reading of manpages to get the nix bindings right seems a bit error prone. It's probably fine, but we'll end up with a few breaking changes as things get fixed. Platform-specific differences can be handled by conditional compilation. |
Error prone maybe, but very necessary. In Rust, nullability is part of the type system. In C, it's just part of an API contract. It's usually pretty obvious when something can be NULL or not, but yes, it's up to nix to figure out what the proper argument types to any function should be.
Well, there needs to be a guarantee that it won't try and read from the pointer... What if someone supplies
|
This makes NixPath more versatile while waiting to see if there will be a NixPath overhaul. Refs nix-rust#221
Sorry for the delay! I need remove myself as a blocker (#236 assemble a team of maintainers). @arcnmx Interested? :) If so, please comment there and / or join the IRC channel! Everything discussed in this thread is pretty much spot on. A lot in nix needs an overhaul. The lib started mostly as a dumping ground for bindings vs. reimplementing them in each lib that needed them. I would like to get a document that covers these kinds of questions and do a pass throughout the lib to unify API styles (see #190). As @arcnmx mentioned, if a system API accepts Specifically regarding |
Thinking more about it, IMO it may be worth creating a separate type for path arguments vs. string arguments.... to get some type safety. Thoughts? |
Well, as far as type invariants are concerned, a path is equivalent to a C string. There's not any advantage in making a wrapper type that asserts you meant it to be a path rather than a
The main con is we move the responsibility of converting a string to a null-terminated string from nix to the caller. The nix error type no longer would have an Another minor con is that The pro is that it makes for a simpler and more transparent nix design that more closely represents the underlying APIs that it's wrapping. A higher level version that accepts and deals with rust strings can be done as part of #190 discussions. As a random data point, I've been using the new API in my own project without issue. I prefer having the cost of conversion to CString be up-front and visible and I haven't found it to be a burden for error handling. My project does the usual fork/exec/etc. dance so it's important that these conversions are done in advance in order to avoid allocations (dangerous if the process is multithreaded) or blowing up a small stack after the fork. |
If we're dropping the |
We could! I think It's kind of tangential to dropping The question really becomes whether we want to drop the |
Sounds good. |
This makes NixPath more versatile while waiting to see if there will be a NixPath overhaul. Refs #221
A relevant comment from @mbr on #245
|
This is a stop gap improvement until the NixPath reform is figured out. refs nix-rust#221
The comment I linked makes me think we should have an opt-in module that provides an additional
|
This is a stop gap improvement until the NixPath reform is figured out. refs nix-rust#221
Thinking a bit more, this complicates the plan to replace
|
This is related again to #190: just how low-level is nix, how much behind-the-scenes magic will there be, etc? I'm not sure I consider nix to be a Rusty API so much as just a more ergonomic and type-safe These methods simply take a C string, it's their definition. Making it more vague is similar to say One could also argue that encouraging people to write higher level abstractions over nix methods for convenience and create a more "rusty" API is advantageous vs providing something almost good enough to be used ad-hoc in rust applications!
This is what
This would be a layer on top of the current nix, I guess. Could have fancy things like |
This is a stop gap improvement until the NixPath reform is figured out. refs nix-rust#221
Ok, I want to get down some of my thoughts on this issue. There are two conflicting desires I'd have for strings and nix:
@arcnmx is prioritizing (1) in #230 which I think is the right choice for zero-cost Rustification of system APIs. At the same time, I want to be able to just write One way to make this available in nix would be to have a * name can be bikeshedded later |
Writing up a couple of ideas that cam up in chat with @arcnmx today (transcript). There's a tension between ergonomics and minimizing overhead and cruft. We came up with two ideas to allow the the convenient and ergonomic
I quite like the second idea, which @arcnmx suggested. It feels like a very clean solution to the problem. |
I do not like the first idea, mainly do to the first counter argument listed. |
I've rebased #230 on to current master and will experiment with the associated type approach. |
In #365 we're discussing |
#444 drops support for Rust < 1.7, which means we can get the let res = try!(try!(try!(try!(
source.with_nix_path(|source| {
target.with_nix_path(|target| {
fstype.with_nix_path(|fstype| {
data.with_nix_path(|data| {
unsafe {
libc::mount(source.as_ptr(),
target.as_ptr(),
fstype.as_ptr(),
flags.bits,
data.as_ptr() as *const libc::c_void)
}
})
})
})
}))))); ―https://github.com/nix-rust/nix/blob/master/src/mount.rs#L60-L75 |
https://github.com/carllerche/nix-rust/blob/00c7905a8a85668d0993420e356a56002ab23905/src/lib.rs#L115
I'm trying to bring back
mount
(#85) and while I can make it work, I'm not 100% sure of what the purpose ofNixPath
is. Could do with a 1-2 sentence explanation of why and when to use it. Its name is confusing formount
because the filesystem type is passed as aNixPath
, though it isn't really a path.The text was updated successfully, but these errors were encountered: