| 437 | /// of this iterator only hold references to the RunEndEncodedArraySpan inputs. |
| 438 | template <typename Left, typename Right> |
| 439 | class MergedRunsIterator { |
| 440 | private: |
| 441 | using LeftIterator = typename Left::Iterator; |
| 442 | using RightIterator = typename Right::Iterator; |
| 443 | |
| 444 | MergedRunsIterator(LeftIterator left_it, RightIterator right_it, |
| 445 | int64_t common_logical_length, int64_t common_logical_pos) |
| 446 | : ree_iterators_{std::move(left_it), std::move(right_it)}, |
| 447 | logical_length_(common_logical_length), |
| 448 | logical_pos_(common_logical_pos) {} |
| 449 | |
| 450 | public: |
| 451 | /// \brief Construct a MergedRunsIterator positioned at logical position 0. |
| 452 | /// |
| 453 | /// Pre-condition: left.length() == right.length() |
| 454 | MergedRunsIterator(const Left& left, const Right& right) |
| 455 | : MergedRunsIterator(left.begin(), right.begin(), left.length(), 0) { |
| 456 | assert(left.length() == right.length()); |
| 457 | } |
| 458 | |
| 459 | static Result<MergedRunsIterator> MakeBegin(const Left& left, const Right& right) { |
| 460 | if (left.length() != right.length()) { |
| 461 | return Status::Invalid( |
| 462 | "MergedRunsIterator expects RunEndEncodedArraySpans of the same length"); |
| 463 | } |
| 464 | return MergedRunsIterator(left, right); |
| 465 | } |
| 466 | |
| 467 | static Result<MergedRunsIterator> MakeEnd(const Left& left, const Right& right) { |
| 468 | if (left.length() != right.length()) { |
| 469 | return Status::Invalid( |
| 470 | "MergedRunsIterator expects RunEndEncodedArraySpans of the same length"); |
| 471 | } |
| 472 | return MergedRunsIterator(left.end(), right.end(), left.length(), left.length()); |
| 473 | } |
| 474 | |
| 475 | /// \brief Return the left RunEndEncodedArraySpan child |
| 476 | const Left& left() const { return std::get<0>(ree_iterators_).span; } |
| 477 | |
| 478 | /// \brief Return the right RunEndEncodedArraySpan child |
| 479 | const Right& right() const { return std::get<1>(ree_iterators_).span; } |
| 480 | |
| 481 | /// \brief Return the initial logical position of the run |
| 482 | /// |
| 483 | /// If is_end(), this is the same as length(). |
| 484 | int64_t logical_position() const { return logical_pos_; } |
| 485 | |
| 486 | /// \brief Whether the iterator is at logical position 0. |
| 487 | bool is_begin() const { return logical_pos_ == 0; } |
| 488 | |
| 489 | /// \brief Whether the iterator has reached the end of both arrays |
| 490 | bool is_end() const { return logical_pos_ == logical_length_; } |
| 491 | |
| 492 | /// \brief Return the logical position immediately after the run. |
| 493 | /// |
| 494 | /// Pre-condition: !is_end() |
| 495 | int64_t run_end() const { |
| 496 | const auto& left_it = std::get<0>(ree_iterators_); |