@@ -1496,28 +1496,12 @@ class ClientImpl {
14961496
14971497 // Streaming handle for reading response body incrementally
14981498 struct StreamHandle {
1499- // Common fields
1499+ // Public fields
15001500 std::unique_ptr<Response> response;
15011501 Error error = Error::Success;
15021502
1503- // Mode 1: Memory buffer (existing behavior)
1504- size_t read_offset_ = 0 ;
1505-
1506- // Mode 2: Socket direct (true streaming)
1507- std::unique_ptr<ClientConnection> connection_; // Socket ownership
1508- std::unique_ptr<Stream> socket_stream_; // SocketStream ownership
1509- Stream *stream_ = nullptr ; // Stream for reading
1510- detail::BodyReader body_reader_; // Body reading state
1511-
1512- // Compression support
1513- std::unique_ptr<detail::decompressor> decompressor_;
1514- std::string decompress_buffer_; // Buffer for decompressed data
1515- size_t decompress_offset_ = 0 ; // Read position in decompress_buffer_
1516-
1517- // Default constructor
1503+ // Constructors and assignment operators
15181504 StreamHandle () = default ;
1519-
1520- // Move-only semantics (non-copyable due to unique_ptr members)
15211505 StreamHandle (const StreamHandle &) = delete ;
15221506 StreamHandle &operator =(const StreamHandle &) = delete ;
15231507 StreamHandle (StreamHandle &&) = default ;
@@ -1526,30 +1510,39 @@ class ClientImpl {
15261510 // Destructor: Cleans up socket connection.
15271511 // In socket direct mode, if the body was not fully read, remaining data
15281512 // is discarded and the connection is closed (cannot be reused).
1529- // This is safe but may leave unread data in the socket buffer.
15301513 ~StreamHandle () = default ;
15311514
1515+ // Check if the handle is valid
15321516 bool is_valid () const {
15331517 return response != nullptr && error == Error::Success;
15341518 }
15351519
1536- // Check if using socket direct mode (true streaming)
1537- bool is_socket_direct_mode () const { return stream_ != nullptr ; }
1538-
15391520 // Read up to len bytes into buf, returns number of bytes read (0 at EOF)
15401521 // Implementation is below decompressor class definition
15411522 ssize_t read (char *buf, size_t len);
15421523
1543- private:
1544- // Read with decompression support (implemented after decompressor class)
1545- ssize_t read_with_decompression (char *buf, size_t len);
1546-
1547- public:
15481524 // Get the last error that occurred during reading (socket direct mode only)
15491525 Error get_read_error () const { return body_reader_.last_error ; }
15501526
15511527 // Check if a read error occurred (socket direct mode only)
15521528 bool has_read_error () const { return body_reader_.has_error (); }
1529+
1530+ private:
1531+ friend class ClientImpl ;
1532+
1533+ // Read with decompression support (implemented after decompressor class)
1534+ ssize_t read_with_decompression (char *buf, size_t len);
1535+
1536+ // Socket connection ownership
1537+ std::unique_ptr<ClientConnection> connection_; // Socket ownership
1538+ std::unique_ptr<Stream> socket_stream_; // SocketStream ownership
1539+ Stream *stream_ = nullptr ; // Stream for reading
1540+ detail::BodyReader body_reader_; // Body reading state
1541+
1542+ // Compression support
1543+ std::unique_ptr<detail::decompressor> decompressor_;
1544+ std::string decompress_buffer_; // Buffer for decompressed data
1545+ size_t decompress_offset_ = 0 ; // Read position in decompress_buffer_
15531546 };
15541547
15551548 // clang-format off
@@ -2923,21 +2916,8 @@ inline bool is_field_value(const std::string &s) { return is_field_content(s); }
29232916inline ssize_t ClientImpl::StreamHandle::read (char *buf, size_t len) {
29242917 if (!is_valid () || !response) { return -1 ; }
29252918
2926- if (is_socket_direct_mode ()) {
2927- // Socket direct mode: read from stream via BodyReader
2928- if (decompressor_) { return read_with_decompression (buf, len); }
2929- return body_reader_.read (buf, len);
2930- } else {
2931- // Memory buffer mode: read from pre-loaded response body
2932- const auto &body = response->body ;
2933- if (read_offset_ >= body.size ()) { return 0 ; }
2934-
2935- auto remaining = body.size () - read_offset_;
2936- auto to_read = (std::min)(len, remaining);
2937- std::memcpy (buf, body.data () + read_offset_, to_read);
2938- read_offset_ += to_read;
2939- return static_cast <ssize_t >(to_read);
2940- }
2919+ if (decompressor_) { return read_with_decompression (buf, len); }
2920+ return body_reader_.read (buf, len);
29412921}
29422922
29432923inline ssize_t ClientImpl::StreamHandle::read_with_decompression (char *buf,
0 commit comments