@@ -311,6 +311,50 @@ Status ReadFieldsSubset(int64_t offset, int32_t metadata_length,
311311 return Status::OK ();
312312}
313313
314+ Result<std::unique_ptr<Message>> ReadMessage (std::shared_ptr<Buffer> metadata,
315+ std::shared_ptr<Buffer> body) {
316+ std::unique_ptr<Message> result;
317+ auto listener = std::make_shared<AssignMessageDecoderListener>(&result);
318+ // If the user does not pass in a body buffer then we assume they are skipping it
319+ MessageDecoder decoder (listener, default_memory_pool (), body == nullptr );
320+
321+ if (metadata->size () < decoder.next_required_size ()) {
322+ return Status::Invalid (" metadata_length should be at least " ,
323+ decoder.next_required_size ());
324+ }
325+
326+ ARROW_RETURN_NOT_OK (decoder.Consume (metadata));
327+
328+ switch (decoder.state ()) {
329+ case MessageDecoder::State::INITIAL :
330+ // Metadata did not request a body so we better not have provided one
331+ DCHECK_EQ (body, nullptr );
332+ return std::move (result);
333+ case MessageDecoder::State::METADATA_LENGTH :
334+ return Status::Invalid (" metadata length is missing from the metadata buffer" );
335+ case MessageDecoder::State::METADATA :
336+ return Status::Invalid (" flatbuffer size " , decoder.next_required_size (),
337+ " invalid. Buffer size: " , metadata->size ());
338+ case MessageDecoder::State::BODY : {
339+ if (body == nullptr ) {
340+ // Caller didn't give a body so just give them a message without body
341+ return std::move (result);
342+ }
343+ if (body->size () != decoder.next_required_size ()) {
344+ return Status::IOError (" Expected body buffer to be " ,
345+ decoder.next_required_size (),
346+ " bytes for message body, got " , body->size ());
347+ }
348+ RETURN_NOT_OK (decoder.Consume (body));
349+ return std::move (result);
350+ }
351+ case MessageDecoder::State::EOS :
352+ return Status::Invalid (" Unexpected empty message in IPC file format" );
353+ default :
354+ return Status::Invalid (" Unexpected state: " , decoder.state ());
355+ }
356+ }
357+
314358Result<std::unique_ptr<Message>> ReadMessage (int64_t offset, int32_t metadata_length,
315359 io::RandomAccessFile* file,
316360 const FieldsLoaderFunction& fields_loader) {
@@ -560,14 +604,15 @@ class MessageDecoder::MessageDecoderImpl {
560604 public:
561605 explicit MessageDecoderImpl (std::shared_ptr<MessageDecoderListener> listener,
562606 State initial_state, int64_t initial_next_required_size,
563- MemoryPool* pool)
607+ MemoryPool* pool, bool skip_body )
564608 : listener_(std::move(listener)),
565609 pool_(pool),
566610 state_(initial_state),
567611 next_required_size_(initial_next_required_size),
568612 chunks_(),
569613 buffered_size_(0 ),
570- metadata_(nullptr ) {}
614+ metadata_(nullptr ),
615+ skip_body_(skip_body) {}
571616
572617 Status ConsumeData (const uint8_t * data, int64_t size) {
573618 if (buffered_size_ == 0 ) {
@@ -798,7 +843,7 @@ class MessageDecoder::MessageDecoderImpl {
798843 RETURN_NOT_OK (CheckMetadataAndGetBodyLength (*metadata_, &body_length));
799844
800845 state_ = State::BODY ;
801- next_required_size_ = body_length;
846+ next_required_size_ = skip_body_ ? 0 : body_length;
802847 RETURN_NOT_OK (listener_->OnBody ());
803848 if (next_required_size_ == 0 ) {
804849 ARROW_ASSIGN_OR_RAISE (auto body, AllocateBuffer (0 , pool_));
@@ -894,19 +939,21 @@ class MessageDecoder::MessageDecoderImpl {
894939 std::vector<std::shared_ptr<Buffer>> chunks_;
895940 int64_t buffered_size_;
896941 std::shared_ptr<Buffer> metadata_; // Must be CPU buffer
942+ bool skip_body_;
897943};
898944
899945MessageDecoder::MessageDecoder (std::shared_ptr<MessageDecoderListener> listener,
900- MemoryPool* pool) {
946+ MemoryPool* pool, bool skip_body ) {
901947 impl_.reset (new MessageDecoderImpl (std::move (listener), State::INITIAL ,
902- kMessageDecoderNextRequiredSizeInitial , pool));
948+ kMessageDecoderNextRequiredSizeInitial , pool,
949+ skip_body));
903950}
904951
905952MessageDecoder::MessageDecoder (std::shared_ptr<MessageDecoderListener> listener,
906953 State initial_state, int64_t initial_next_required_size,
907- MemoryPool* pool) {
954+ MemoryPool* pool, bool skip_body ) {
908955 impl_.reset (new MessageDecoderImpl (std::move (listener), initial_state,
909- initial_next_required_size, pool));
956+ initial_next_required_size, pool, skip_body ));
910957}
911958
912959MessageDecoder::~MessageDecoder () {}
0 commit comments