(t reflect.Type, vx, vy reflect.Value)
| 416 | } |
| 417 | |
| 418 | func (s *state) compareSlice(t reflect.Type, vx, vy reflect.Value) { |
| 419 | isSlice := t.Kind() == reflect.Slice |
| 420 | if isSlice && (vx.IsNil() || vy.IsNil()) { |
| 421 | s.report(vx.IsNil() && vy.IsNil(), 0) |
| 422 | return |
| 423 | } |
| 424 | |
| 425 | // NOTE: It is incorrect to call curPtrs.Push on the slice header pointer |
| 426 | // since slices represents a list of pointers, rather than a single pointer. |
| 427 | // The pointer checking logic must be handled on a per-element basis |
| 428 | // in compareAny. |
| 429 | // |
| 430 | // A slice header (see reflect.SliceHeader) in Go is a tuple of a starting |
| 431 | // pointer P, a length N, and a capacity C. Supposing each slice element has |
| 432 | // a memory size of M, then the slice is equivalent to the list of pointers: |
| 433 | // [P+i*M for i in range(N)] |
| 434 | // |
| 435 | // For example, v[:0] and v[:1] are slices with the same starting pointer, |
| 436 | // but they are clearly different values. Using the slice pointer alone |
| 437 | // violates the assumption that equal pointers implies equal values. |
| 438 | |
| 439 | step := SliceIndex{&sliceIndex{pathStep: pathStep{typ: t.Elem()}, isSlice: isSlice}} |
| 440 | withIndexes := func(ix, iy int) SliceIndex { |
| 441 | if ix >= 0 { |
| 442 | step.vx, step.xkey = vx.Index(ix), ix |
| 443 | } else { |
| 444 | step.vx, step.xkey = reflect.Value{}, -1 |
| 445 | } |
| 446 | if iy >= 0 { |
| 447 | step.vy, step.ykey = vy.Index(iy), iy |
| 448 | } else { |
| 449 | step.vy, step.ykey = reflect.Value{}, -1 |
| 450 | } |
| 451 | return step |
| 452 | } |
| 453 | |
| 454 | // Ignore options are able to ignore missing elements in a slice. |
| 455 | // However, detecting these reliably requires an optimal differencing |
| 456 | // algorithm, for which diff.Difference is not. |
| 457 | // |
| 458 | // Instead, we first iterate through both slices to detect which elements |
| 459 | // would be ignored if standing alone. The index of non-discarded elements |
| 460 | // are stored in a separate slice, which diffing is then performed on. |
| 461 | var indexesX, indexesY []int |
| 462 | var ignoredX, ignoredY []bool |
| 463 | for ix := 0; ix < vx.Len(); ix++ { |
| 464 | ignored := s.statelessCompare(withIndexes(ix, -1)).NumDiff == 0 |
| 465 | if !ignored { |
| 466 | indexesX = append(indexesX, ix) |
| 467 | } |
| 468 | ignoredX = append(ignoredX, ignored) |
| 469 | } |
| 470 | for iy := 0; iy < vy.Len(); iy++ { |
| 471 | ignored := s.statelessCompare(withIndexes(-1, iy)).NumDiff == 0 |
| 472 | if !ignored { |
| 473 | indexesY = append(indexesY, iy) |
| 474 | } |
| 475 | ignoredY = append(ignoredY, ignored) |
no test coverage detected