Phoenix500526 commented on code in PR #10277:
URL: https://github.com/apache/arrow-rs/pull/10277#discussion_r3600765700


##########
arrow-ipc/src/writer.rs:
##########
@@ -725,6 +724,67 @@ impl IpcDataGenerator {
         })
     }
 
+    /// Encode dictionary batches and the record batch to output buffers, 
skipping the
+    /// intermediate body `Vec<u8>` allocations for uncompressed record batch 
buffers.
+    fn encode_to_buffers(
+        &self,
+        batch: &RecordBatch,
+        dictionary_tracker: &mut DictionaryTracker,
+        write_options: &IpcWriteOptions,
+        ipc_write_context: &mut IpcWriteContext,
+        out: &mut Vec<Buffer>,
+    ) -> Result<IpcWriteMetadata, ArrowError> {
+        let encoded_dictionaries =
+            self.encode_all_dicts(batch, dictionary_tracker, write_options, 
ipc_write_context)?;
+
+        let mut dictionary_block_sizes = 
Vec::with_capacity(encoded_dictionaries.len());
+        for dict in encoded_dictionaries {
+            dictionary_block_sizes.push(encoded_data_to_buffers(out, dict, 
write_options)?);
+        }
+
+        let capacity = batch
+            .columns()
+            .iter()
+            .map(|a| estimate_encoded_buffer_count(a.data_type()))
+            .sum();
+        let mut encoded_buffers: Vec<EncodedBuffer> = 
Vec::with_capacity(capacity);
+        let (ipc_message, body_len, tail_pad) = self.record_batch_to_bytes(
+            batch,
+            write_options,
+            ipc_write_context,
+            &mut IpcBodySink::Collect(&mut encoded_buffers),
+        )?;
+
+        let alignment = write_options.alignment;
+        let alignment_mask = usize::from(alignment - 1);
+        let prefix_size = if write_options.write_legacy_ipc_format {
+            4
+        } else {
+            8
+        };
+        let ipc_message_len = ipc_message.len();
+        let aligned_size = (ipc_message_len + prefix_size + alignment_mask) & 
!alignment_mask;
+        push_continuation_buffer(out, write_options, (aligned_size - 
prefix_size) as i32)?;
+        out.push(Buffer::from(ipc_message));
+        push_padding_buffer(out, aligned_size - ipc_message_len - prefix_size);
+        for enc in encoded_buffers {
+            let len = enc.len();
+            let buffer = match enc {
+                EncodedBuffer::Raw(buffer) => buffer,
+                EncodedBuffer::Compressed(bytes) => Buffer::from(bytes),
+            };
+            out.push(buffer);
+            push_padding_buffer(out, pad_to_alignment(alignment, len));
+        }

Review Comment:
   Good catch. I refactored this to use a shared internal `IpcMessageSink` for 
the final framed IPC message emission. I kep `IpcBodySink` focused on 
materializing the record batch body buffers, and added `IpcMessageSink` one 
layer above it to handle where the complete framed IPC message goes: either a 
`Write` sink or ordered `Buffer`s.
   
   With that, `IpcDataGenerator::write` and `encode_to_buffers` now share the 
same `write_to_sink` path instead of duplicating dictionary/message framing 
logic. 



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to