diff --git a/Cargo.toml b/Cargo.toml index d4c6b32..25b5fde 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ggemini" -version = "0.15.1" +version = "0.16.0" edition = "2021" license = "MIT" readme = "README.md" diff --git a/src/gio/memory_input_stream.rs b/src/gio/memory_input_stream.rs index c953bc5..c588f9d 100644 --- a/src/gio/memory_input_stream.rs +++ b/src/gio/memory_input_stream.rs @@ -53,19 +53,27 @@ pub fn for_memory_input_stream_async( Some(&cancellable.clone()), move |result| match result { Ok(bytes) => { - total += bytes.len(); - on_chunk(bytes.len(), total); + let len = bytes.len(); // calculate once - if total > limit { - return on_complete(Err(Error::BytesTotal(total, limit))); - } - - if bytes.len() == 0 { - return on_complete(Ok((memory_input_stream, total))); - } + total += len; + on_chunk(len, total); memory_input_stream.add_bytes(&bytes); + // prevent memory overflow on size `limit` reached + // * add last received bytes into the `memory_input_stream` anyway (to prevent data lost), + // it's safe because limited to the `chunk` size + if total > limit { + return on_complete(Err(Error::BytesTotal(memory_input_stream, total, limit))); + } + + // is the next iteration required? + if len < chunk // some servers may close the connection after first chunk request (@TODO this condition wants review) + || len == 0 + { + return on_complete(Ok((memory_input_stream, total))); + } + // continue reading.. for_memory_input_stream_async( memory_input_stream, @@ -76,9 +84,7 @@ pub fn for_memory_input_stream_async( (on_chunk, on_complete), ) } - Err(e) => { - on_complete(Err(Error::InputStream(e))); - } + Err(e) => on_complete(Err(Error::InputStream(memory_input_stream, e))), }, ) } diff --git a/src/gio/memory_input_stream/error.rs b/src/gio/memory_input_stream/error.rs index 673906c..6b8ae86 100644 --- a/src/gio/memory_input_stream/error.rs +++ b/src/gio/memory_input_stream/error.rs @@ -2,17 +2,17 @@ use std::fmt::{Display, Formatter, Result}; #[derive(Debug)] pub enum Error { - BytesTotal(usize, usize), - InputStream(glib::Error), + BytesTotal(gio::MemoryInputStream, usize, usize), + InputStream(gio::MemoryInputStream, glib::Error), } impl Display for Error { fn fmt(&self, f: &mut Formatter) -> Result { match self { - Self::BytesTotal(total, limit) => { + Self::BytesTotal(_, total, limit) => { write!(f, "Bytes total limit reached: {total} / {limit}") } - Self::InputStream(e) => { + Self::InputStream(_, e) => { write!(f, "Input stream error: {e}") } }