-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcontext.go
More file actions
88 lines (74 loc) · 2.85 KB
/
Copy pathcontext.go
File metadata and controls
88 lines (74 loc) · 2.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package comparator
import (
"context"
"fmt"
)
// ContextComparator is implemented by the comparators returned from New,
// NewWithOptions, and NewDiffComparer. Its methods accept a context.Context so
// long-running comparisons over large structures can be canceled or bounded by
// a deadline.
//
// A canceled context causes the comparison to stop early and return an error
// that wraps both ErrCanceled and the context's own error.
type ContextComparator interface {
// EqualCtx behaves like Comparator.Equal but honors ctx cancellation.
EqualCtx(ctx context.Context, a, b any) (bool, error)
// DiffCtx behaves like Comparator.Diff but honors ctx cancellation.
DiffCtx(ctx context.Context, a, b any) ([]Difference, error)
// CompareWithDiffCtx behaves like DiffComparer.CompareWithDiff but honors
// ctx cancellation.
CompareWithDiffCtx(ctx context.Context, a, b any) (*DiffResult, error)
}
// ctxError wraps the context's error together with ErrCanceled so that callers
// can branch with errors.Is on either sentinel.
func ctxError(ctx context.Context) error {
if err := ctx.Err(); err != nil {
return fmt.Errorf("%w: %w", ErrCanceled, err)
}
return ErrCanceled
}
// EqualCtx performs a deep equality check that stops early if ctx is canceled.
func (c *defaultComparator) EqualCtx(ctx context.Context, a, b any) (bool, error) {
c.ctx = ctx
defer func() { c.ctx = nil }()
result := c.Equal(a, b)
if c.cancelled {
return false, ctxError(ctx)
}
return result, nil
}
// DiffCtx collects differences and stops early if ctx is canceled.
func (c *defaultComparator) DiffCtx(ctx context.Context, a, b any) ([]Difference, error) {
c.ctx = ctx
defer func() { c.ctx = nil }()
diffs, _ := c.Diff(a, b)
if c.cancelled {
return nil, ctxError(ctx)
}
return diffs, nil
}
// CompareWithDiffCtx performs a comprehensive comparison and stops early if ctx
// is canceled.
func (c *defaultComparator) CompareWithDiffCtx(ctx context.Context, a, b any) (*DiffResult, error) {
c.ctx = ctx
defer func() { c.ctx = nil }()
result := c.CompareWithDiff(a, b)
if c.cancelled {
return nil, ctxError(ctx)
}
return result, nil
}
// EqualCtx is a package-level convenience for a one-off context-aware equality
// check.
func EqualCtx(ctx context.Context, a, b any, opts ...Option) (bool, error) {
return NewWithOptions(opts...).(ContextComparator).EqualCtx(ctx, a, b)
}
// DiffCtx is a package-level convenience for a one-off context-aware diff.
func DiffCtx(ctx context.Context, a, b any, opts ...Option) ([]Difference, error) {
return NewWithOptions(opts...).(ContextComparator).DiffCtx(ctx, a, b)
}
// CompareWithDiffCtx is a package-level convenience for a one-off context-aware
// comprehensive comparison.
func CompareWithDiffCtx(ctx context.Context, a, b any, opts ...Option) (*DiffResult, error) {
return NewDiffComparer(opts...).(ContextComparator).CompareWithDiffCtx(ctx, a, b)
}