- macro_rules! read_line { () => { {
- let mut line = String::new();
- #[cfg(feature = "tokio")]
- let bytes_read = reader.read_line(&mut line).await?;
- #[cfg(not(feature = "tokio"))]
- let bytes_read = reader.read_line(&mut line)?;
-
- match bytes_read {
- 0 => None,
- _ => {
- // Remove trailing CRLF
- if line.ends_with('\n') { line.pop(); if line.ends_with('\r') { line.pop(); } }
- Some(line)
- },
- }
- } } }
+ macro_rules! read_line {
+ () => { read_line!(0) };
+ ($retry_count: expr) => { {
+ let mut line = String::new();
+ let mut timeout_count: u64 = 0;
+ let bytes_read = loop {
+ #[cfg(feature = "tokio")]
+ let read_res = reader.read_line(&mut line).await;
+ #[cfg(not(feature = "tokio"))]
+ let read_res = reader.read_line(&mut line);
+ match read_res {
+ Ok(bytes_read) => break bytes_read,
+ Err(e) if e.kind() == std::io::ErrorKind::WouldBlock => {
+ timeout_count += 1;
+ if timeout_count > $retry_count {
+ return Err(e);
+ } else {
+ continue;
+ }
+ }
+ Err(e) => return Err(e),
+ }
+ };
+
+ match bytes_read {
+ 0 => None,
+ _ => {
+ // Remove trailing CRLF
+ if line.ends_with('\n') { line.pop(); if line.ends_with('\r') { line.pop(); } }
+ Some(line)
+ },
+ }
+ } }
+ }