(A: T[], B: T[])
| 244 | * ``` |
| 245 | */ |
| 246 | export function diff<T>(A: T[], B: T[]): DiffResult<T>[] { |
| 247 | const prefixCommon = createCommon(A, B); |
| 248 | A = A.slice(prefixCommon.length); |
| 249 | B = B.slice(prefixCommon.length); |
| 250 | const swapped = B.length > A.length; |
| 251 | [A, B] = swapped ? [B, A] : [A, B]; |
| 252 | const M = A.length; |
| 253 | const N = B.length; |
| 254 | if (!M && !N && !prefixCommon.length) return []; |
| 255 | if (!N) { |
| 256 | return [ |
| 257 | ...prefixCommon.map((value) => ({ type: "common", value })), |
| 258 | ...A.map((value) => ({ type: swapped ? "added" : "removed", value })), |
| 259 | ] as DiffResult<T>[]; |
| 260 | } |
| 261 | const offset = N; |
| 262 | const delta = M - N; |
| 263 | const length = M + N + 1; |
| 264 | const fp: FarthestPoint[] = Array.from({ length }, () => ({ y: -1, id: -1 })); |
| 265 | |
| 266 | /** |
| 267 | * Note: this buffer is used to save memory and improve performance. The first |
| 268 | * half is used to save route and the last half is used to save diff type. |
| 269 | */ |
| 270 | const routes = new Uint32Array((M * N + length + 1) * 2); |
| 271 | const diffTypesPtrOffset = routes.length / 2; |
| 272 | let ptr = 0; |
| 273 | |
| 274 | function snake<T>( |
| 275 | k: number, |
| 276 | A: T[], |
| 277 | B: T[], |
| 278 | slide?: FarthestPoint, |
| 279 | down?: FarthestPoint, |
| 280 | ): FarthestPoint { |
| 281 | const M = A.length; |
| 282 | const N = B.length; |
| 283 | const fp = createFp(k, M, routes, diffTypesPtrOffset, ptr, slide, down); |
| 284 | ptr = fp.id; |
| 285 | while (fp.y + k < M && fp.y < N && A[fp.y + k] === B[fp.y]) { |
| 286 | const prev = fp.id; |
| 287 | ptr++; |
| 288 | fp.id = ptr; |
| 289 | fp.y += 1; |
| 290 | routes[ptr] = prev; |
| 291 | routes[ptr + diffTypesPtrOffset] = COMMON; |
| 292 | } |
| 293 | return fp; |
| 294 | } |
| 295 | |
| 296 | let currentFp = fp[delta + offset]; |
| 297 | assertFp(currentFp); |
| 298 | let p = -1; |
| 299 | while (currentFp.y < N) { |
| 300 | p = p + 1; |
| 301 | for (let k = -p; k < delta; ++k) { |
| 302 | const index = k + offset; |
| 303 | fp[index] = snake(k, A, B, fp[index - 1], fp[index + 1]); |
no test coverage detected