So here are my ideas. They are very worse-is-better at this point.

* Failing to perform a basic I/O operation should result in a call to the `io_error` condition (default behavior: fail task) and should set an internal flag saying that this stream is dead. Stream constructors like `open` should return a dead stream. Operations like read or write on dead streams should be no-ops.

Rationale: When in doubt as to the right semantics, it's best to just delegate to the OS. The OS has the concept of a stream in an error state already; we can possibly just piggyback on its concept of a stream in the error state in some cases and not have to store a flag at all. We could store the internal FD or FILE* as `Option<c_int>` or `Option<*FILE>` respectively to handle streams that didn't succeed to open or were closed.

* Stream readers such as `read_uint` should be duplicated into two methods for convenience: `read_uint` and `try_read_uint`. The former just delegates to the latter with `.get()`.

Rationale: It's a bit of a burden on library implementors, but this is a classic convenience-versus-robustness tradeoff. It's like array indexing `[]` on `[T]` returning `T` instead of `Option<T>`: it's extra work for the library, but well worth it for programmer convenience. In other words, this isn't really an I/O specific question at all: we have this tradeoff throughout the library and language, and usually we've resolved it by having convenient `foo()` and robust `try_foo()` methods (under a variety of naming conventions). This is no different.

Patrick
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to