From 9b1e75480bb133a10f454903e38d3fcd9abe7f54 Mon Sep 17 00:00:00 2001 From: ivmarkov Date: Sat, 24 Aug 2024 07:32:28 +0000 Subject: [PATCH 1/5] Clarify Read trait blocking behavior --- embedded-io/src/lib.rs | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/embedded-io/src/lib.rs b/embedded-io/src/lib.rs index 9f95e636a..62028c222 100644 --- a/embedded-io/src/lib.rs +++ b/embedded-io/src/lib.rs @@ -300,16 +300,23 @@ impl std::error::Error for WriteFmtError {} pub trait Read: ErrorType { /// Read some bytes from this source into the specified buffer, returning how many bytes were read. /// - /// If no bytes are currently available to read, this function blocks until at least one byte is available. + /// If no bytes are currently available to read: + /// - The method blocks until at least one byte becomes available; + /// - Once at least one (or more) bytes become available, a non-zero amount of those is read to the + /// beginning of `buf`, and the amount is returned, *without waiting or blocking any further for + /// more bytes to become available*. /// - /// If bytes are available, a non-zero amount of bytes is read to the beginning of `buf`, and the amount - /// is returned. It is not guaranteed that *all* available bytes are returned, it is possible for the - /// implementation to read an amount of bytes less than `buf.len()` while there are more bytes immediately - /// available. + /// If bytes are available to read: + /// - A non-zero amount of bytes is read to the beginning of `buf`, and the amount is returned immediately, + /// *without blocking and waiting for more bytes to become available*; + /// - It is not guaranteed that *all* available bytes are returned, it is possible for the implementation to + /// read an amount of bytes less than `buf.len()` while there are more bytes immediately available. /// - /// If the reader is at end-of-file (EOF), `Ok(0)` is returned. There is no guarantee that a reader at EOF - /// will always be so in the future, for example a reader can stop being at EOF if another process appends - /// more bytes to the underlying file. + /// This blocking behavior is important for the cases where `Read` represents the "read" leg of a pipe-like + /// protocol (a socket, a pipe, a serial line etc.). The semantics is that the caller - by passing a non-empty + /// buffer - does expect _some_ data (one or more bytes) - but _not necessarily `buf.len()` or more bytes_ - + /// to become available, before the peer represented by `Read` would stop sending bytes due to + /// application-specific reasons (as in the peer waiting for a response to the data it had sent so far). /// /// If `buf.len() == 0`, `read` returns without blocking, with either `Ok(0)` or an error. /// The `Ok(0)` doesn't indicate EOF, unlike when called with a non-empty buffer. From 45fcad0cd5c329a90df7f066aaffb6741a414498 Mon Sep 17 00:00:00 2001 From: ivmarkov Date: Sat, 24 Aug 2024 13:01:06 +0300 Subject: [PATCH 2/5] Update embedded-io/src/lib.rs Co-authored-by: James Munns --- embedded-io/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embedded-io/src/lib.rs b/embedded-io/src/lib.rs index 62028c222..fcf465f42 100644 --- a/embedded-io/src/lib.rs +++ b/embedded-io/src/lib.rs @@ -302,7 +302,7 @@ pub trait Read: ErrorType { /// /// If no bytes are currently available to read: /// - The method blocks until at least one byte becomes available; - /// - Once at least one (or more) bytes become available, a non-zero amount of those is read to the + /// - Once at least one (or more) bytes become available, a non-zero amount of those is copied to the /// beginning of `buf`, and the amount is returned, *without waiting or blocking any further for /// more bytes to become available*. /// From 92dbaf2d03dbf8d6910cee4fc3b867c1bcf3746a Mon Sep 17 00:00:00 2001 From: ivmarkov Date: Sat, 24 Aug 2024 11:48:15 +0000 Subject: [PATCH 3/5] Re-add an unintentionally removed paragraph --- embedded-io/src/lib.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/embedded-io/src/lib.rs b/embedded-io/src/lib.rs index fcf465f42..a9abf9f42 100644 --- a/embedded-io/src/lib.rs +++ b/embedded-io/src/lib.rs @@ -318,6 +318,10 @@ pub trait Read: ErrorType { /// to become available, before the peer represented by `Read` would stop sending bytes due to /// application-specific reasons (as in the peer waiting for a response to the data it had sent so far). /// + /// If the reader is at end-of-file (EOF), `Ok(0)` is returned. There is no guarantee that a reader at EOF + /// will always be so in the future, for example a reader can stop being at EOF if another process appends + /// more bytes to the underlying file. + /// /// If `buf.len() == 0`, `read` returns without blocking, with either `Ok(0)` or an error. /// The `Ok(0)` doesn't indicate EOF, unlike when called with a non-empty buffer. fn read(&mut self, buf: &mut [u8]) -> Result; From f3558ac6f10a2f9d6403237f86edea210a9bfc0b Mon Sep 17 00:00:00 2001 From: ivmarkov Date: Mon, 26 Aug 2024 07:32:57 +0000 Subject: [PATCH 4/5] Add identical changes to the async Read variant --- embedded-io-async/src/lib.rs | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/embedded-io-async/src/lib.rs b/embedded-io-async/src/lib.rs index 7c0ac2d55..0fb8a2576 100644 --- a/embedded-io-async/src/lib.rs +++ b/embedded-io-async/src/lib.rs @@ -19,12 +19,23 @@ pub use embedded_io::{ pub trait Read: ErrorType { /// Read some bytes from this source into the specified buffer, returning how many bytes were read. /// - /// If no bytes are currently available to read, this function waits until at least one byte is available. - /// - /// If bytes are available, a non-zero amount of bytes is read to the beginning of `buf`, and the amount - /// is returned. It is not guaranteed that *all* available bytes are returned, it is possible for the - /// implementation to read an amount of bytes less than `buf.len()` while there are more bytes immediately - /// available. + /// If no bytes are currently available to read: + /// - The method waits until at least one byte becomes available; + /// - Once at least one (or more) bytes become available, a non-zero amount of those is copied to the + /// beginning of `buf`, and the amount is returned, *without waiting any further for more bytes to + /// become available*. + /// + /// If bytes are available to read: + /// - A non-zero amount of bytes is read to the beginning of `buf`, and the amount is returned immediately, + /// *without waiting for more bytes to become available*; + /// - It is not guaranteed that *all* available bytes are returned, it is possible for the implementation to + /// read an amount of bytes less than `buf.len()` while there are more bytes immediately available. + /// + /// This waiting behavior is important for the cases where `Read` represents the "read" leg of a pipe-like + /// protocol (a socket, a pipe, a serial line etc.). The semantics is that the caller - by passing a non-empty + /// buffer - does expect _some_ data (one or more bytes) - but _not necessarily `buf.len()` or more bytes_ - + /// to become available, before the peer represented by `Read` would stop sending bytes due to + /// application-specific reasons (as in the peer waiting for a response to the data it had sent so far). /// /// If the reader is at end-of-file (EOF), `Ok(0)` is returned. There is no guarantee that a reader at EOF /// will always be so in the future, for example a reader can stop being at EOF if another process appends From d7454184366fdbefb590bdee0cb7a8a21ce4e886 Mon Sep 17 00:00:00 2001 From: ivmarkov Date: Sun, 8 Sep 2024 07:51:22 +0000 Subject: [PATCH 5/5] Address review feedback --- embedded-io-async/src/lib.rs | 6 ++++-- embedded-io/src/lib.rs | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/embedded-io-async/src/lib.rs b/embedded-io-async/src/lib.rs index 0fb8a2576..eef50ebcd 100644 --- a/embedded-io-async/src/lib.rs +++ b/embedded-io-async/src/lib.rs @@ -28,8 +28,10 @@ pub trait Read: ErrorType { /// If bytes are available to read: /// - A non-zero amount of bytes is read to the beginning of `buf`, and the amount is returned immediately, /// *without waiting for more bytes to become available*; - /// - It is not guaranteed that *all* available bytes are returned, it is possible for the implementation to - /// read an amount of bytes less than `buf.len()` while there are more bytes immediately available. + /// + /// Note that once some bytes are available to read, it is *not* guaranteed that all available bytes are returned. + /// It is possible for the implementation to read an amount of bytes less than `buf.len()` while there are more + /// bytes immediately available. /// /// This waiting behavior is important for the cases where `Read` represents the "read" leg of a pipe-like /// protocol (a socket, a pipe, a serial line etc.). The semantics is that the caller - by passing a non-empty diff --git a/embedded-io/src/lib.rs b/embedded-io/src/lib.rs index a9abf9f42..f050abb1d 100644 --- a/embedded-io/src/lib.rs +++ b/embedded-io/src/lib.rs @@ -309,8 +309,10 @@ pub trait Read: ErrorType { /// If bytes are available to read: /// - A non-zero amount of bytes is read to the beginning of `buf`, and the amount is returned immediately, /// *without blocking and waiting for more bytes to become available*; - /// - It is not guaranteed that *all* available bytes are returned, it is possible for the implementation to - /// read an amount of bytes less than `buf.len()` while there are more bytes immediately available. + /// + /// Note that once some bytes are available to read, it is *not* guaranteed that all available bytes are returned. + /// It is possible for the implementation to read an amount of bytes less than `buf.len()` while there are more + /// bytes immediately available. /// /// This blocking behavior is important for the cases where `Read` represents the "read" leg of a pipe-like /// protocol (a socket, a pipe, a serial line etc.). The semantics is that the caller - by passing a non-empty