| 401 | } // namespace |
| 402 | |
| 403 | Result<std::unique_ptr<Message>> ReadMessage(std::shared_ptr<Buffer> metadata, |
| 404 | std::shared_ptr<Buffer> body) { |
| 405 | std::unique_ptr<Message> result; |
| 406 | auto listener = std::make_shared<AssignMessageDecoderListener>(&result); |
| 407 | // If the user does not pass in a body buffer then we assume they are skipping it |
| 408 | MessageDecoder decoder(listener, default_memory_pool(), body == nullptr); |
| 409 | |
| 410 | if (metadata->size() < decoder.next_required_size()) { |
| 411 | return Status::Invalid("metadata_length should be at least ", |
| 412 | decoder.next_required_size()); |
| 413 | } |
| 414 | |
| 415 | ARROW_RETURN_NOT_OK(decoder.Consume(metadata)); |
| 416 | if (decoder.buffered_size() > 0) { |
| 417 | return Status::Invalid("Message metadata too long by ", decoder.buffered_size(), |
| 418 | " bytes"); |
| 419 | } |
| 420 | |
| 421 | switch (decoder.state()) { |
| 422 | case MessageDecoder::State::INITIAL: |
| 423 | // Metadata did not request a body so we better not have provided one |
| 424 | DCHECK_EQ(body, nullptr); |
| 425 | return result; |
| 426 | case MessageDecoder::State::METADATA_LENGTH: |
| 427 | return Status::Invalid("metadata length is missing from the metadata buffer"); |
| 428 | case MessageDecoder::State::METADATA: |
| 429 | return Status::Invalid("flatbuffer size ", decoder.next_required_size(), |
| 430 | " invalid. Buffer size: ", metadata->size()); |
| 431 | case MessageDecoder::State::BODY: { |
| 432 | if (body == nullptr) { |
| 433 | // Caller didn't give a body so just give them a message without body |
| 434 | return result; |
| 435 | } |
| 436 | if (body->size() != decoder.next_required_size()) { |
| 437 | return Status::IOError("Expected body buffer to be ", |
| 438 | decoder.next_required_size(), |
| 439 | " bytes for message body, got ", body->size()); |
| 440 | } |
| 441 | RETURN_NOT_OK(decoder.Consume(body)); |
| 442 | return result; |
| 443 | } |
| 444 | case MessageDecoder::State::EOS: |
| 445 | return Status::Invalid("Unexpected empty message in IPC file format"); |
| 446 | default: |
| 447 | return Status::Invalid("Unexpected state: ", decoder.state()); |
| 448 | } |
| 449 | } |
| 450 | |
| 451 | // Common helper for the two ReadMessage overloads that take a file + offset. |
| 452 | // When body_length is provided, metadata and body are read in a single IO. |