| 971 | } |
| 972 | |
| 973 | Status VisitEditScript( |
| 974 | const Array& edits, |
| 975 | const std::function<Status(int64_t delete_begin, int64_t delete_end, |
| 976 | int64_t insert_begin, int64_t insert_end)>& visitor) { |
| 977 | static const auto edits_type = |
| 978 | struct_({field("insert", boolean()), field("run_length", int64())}); |
| 979 | DCHECK(edits.type()->Equals(*edits_type)); |
| 980 | DCHECK_GE(edits.length(), 1); |
| 981 | |
| 982 | auto insert = checked_pointer_cast<BooleanArray>( |
| 983 | checked_cast<const StructArray&>(edits).field(0)); |
| 984 | auto run_lengths = |
| 985 | checked_pointer_cast<Int64Array>(checked_cast<const StructArray&>(edits).field(1)); |
| 986 | |
| 987 | DCHECK(!insert->Value(0)); |
| 988 | |
| 989 | auto length = run_lengths->Value(0); |
| 990 | int64_t base_begin, base_end, target_begin, target_end; |
| 991 | base_begin = base_end = target_begin = target_end = length; |
| 992 | for (int64_t i = 1; i < edits.length(); ++i) { |
| 993 | if (insert->Value(i)) { |
| 994 | ++target_end; |
| 995 | } else { |
| 996 | ++base_end; |
| 997 | } |
| 998 | length = run_lengths->Value(i); |
| 999 | if (length != 0) { |
| 1000 | RETURN_NOT_OK(visitor(base_begin, base_end, target_begin, target_end)); |
| 1001 | base_begin = base_end = base_end + length; |
| 1002 | target_begin = target_end = target_end + length; |
| 1003 | } |
| 1004 | } |
| 1005 | if (length == 0) { |
| 1006 | return visitor(base_begin, base_end, target_begin, target_end); |
| 1007 | } |
| 1008 | return Status::OK(); |
| 1009 | } |
| 1010 | |
| 1011 | Result<std::shared_ptr<StructArray>> Diff(const Array& base, const Array& target, |
| 1012 | MemoryPool* pool) { |