Skip to content

Commit 98f86a7

Browse files
committed
Refactor PatchSet to be contained in a separate package for reusability.
1 parent f03a67e commit 98f86a7

File tree

6 files changed

+537
-490
lines changed

6 files changed

+537
-490
lines changed
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/*
2+
Copyright 2025 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package common
18+
19+
// Patch represents a single layer of modifications (additions/updates)
20+
// and deletions for a set of key-value pairs. It's used as a building
21+
// block for the patchSet.
22+
type Patch[K comparable, V any] struct {
23+
modified map[K]V
24+
deleted map[K]bool
25+
}
26+
27+
// Set marks a key-value pair as modified in the current patch.
28+
// If the key was previously marked as deleted, the deletion mark is removed.
29+
func (p *Patch[K, V]) Set(key K, value V) {
30+
p.modified[key] = value
31+
delete(p.deleted, key)
32+
}
33+
34+
// Delete marks a key as deleted in the current patch.
35+
// If the key was previously marked as modified, the modification is removed.
36+
func (p *Patch[K, V]) Delete(key K) {
37+
delete(p.modified, key)
38+
p.deleted[key] = true
39+
}
40+
41+
// Get retrieves the modified value for a key within this specific patch.
42+
// It returns the value and true if the key was found in this patch
43+
// or zero value and false otherwise.
44+
func (p *Patch[K, V]) Get(key K) (value V, found bool) {
45+
value, found = p.modified[key]
46+
return value, found
47+
}
48+
49+
// IsDeleted checks if the key is marked as deleted within this specific patch.
50+
func (p *Patch[K, V]) IsDeleted(key K) bool {
51+
return p.deleted[key]
52+
}
53+
54+
// NewPatch creates a new, empty patch with no modifications or deletions.
55+
func NewPatch[K comparable, V any]() *Patch[K, V] {
56+
return &Patch[K, V]{
57+
modified: make(map[K]V),
58+
deleted: make(map[K]bool),
59+
}
60+
}
61+
62+
// NewPatchFromMap creates a new patch initialized with the data from the provided map
63+
// the data supplied is recorded as modified in the patch.
64+
func NewPatchFromMap[M ~map[K]V, K comparable, V any](source M) *Patch[K, V] {
65+
if source == nil {
66+
source = make(M)
67+
}
68+
69+
return &Patch[K, V]{
70+
modified: source,
71+
deleted: make(map[K]bool),
72+
}
73+
}
74+
75+
// mergePatchesInPlace merges two patches into one, while modifying patch a
76+
// inplace taking records in b as a priority when overwrites are required
77+
func mergePatchesInPlace[K comparable, V any](a *Patch[K, V], b *Patch[K, V]) *Patch[K, V] {
78+
for key, value := range b.modified {
79+
a.Set(key, value)
80+
}
81+
82+
for key := range b.deleted {
83+
a.Delete(key)
84+
}
85+
86+
return a
87+
}

0 commit comments

Comments
 (0)