internal/api/utils.go (84 lines of code) (raw):

// Copyright 2025 Microsoft Corporation // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package api import ( "iter" "slices" "strings" semver "github.com/hashicorp/go-version" ) const ( OpenShiftVersionPrefix = "openshift-v" ) // Ptr returns a pointer to p. func Ptr[T any](p T) *T { return &p } // NewOpenShiftVersion parses the given version, stripping off any // OpenShift prefix ("openshift-"), and returns a new Version. func NewOpenShiftVersion(v string) (*semver.Version, error) { return semver.NewVersion(strings.Replace(v, OpenShiftVersionPrefix, "", 1)) } // DeleteNilsFromPtrSlice returns a slice with nil pointers removed. func DeleteNilsFromPtrSlice[S ~[]*E, E any](s S) S { return slices.DeleteFunc(s, func(e *E) bool { return e == nil }) } // NonNilSliceValues returns an iterator over index-value pairs in a slice // of pointers in the usual order, but skipping over nils. func NonNilSliceValues[E any](a []*E) iter.Seq2[int, *E] { return NonNilValues(slices.All(a)) } // NonNilValues returns an iterator over a sequence of pairs of values that skips // pairs where the second value in the pair is nil. func NonNilValues[K any, V any](seq iter.Seq2[K, *V]) iter.Seq2[K, *V] { return func(yield func(K, *V) bool) { for k, v := range seq { if v != nil { if !yield(k, v) { return } } } } } // StringSliceToStringPtrSlice converts a slice of strings to a slice of string pointers. func StringSliceToStringPtrSlice(s []string) []*string { out := make([]*string, len(s)) for index, item := range s { out[index] = Ptr(item) } return out } // StringPtrSliceToStringSlice converts a slice of string pointers to a slice of strings. func StringPtrSliceToStringSlice(s []*string) []string { s = DeleteNilsFromPtrSlice(s) out := make([]string, 0, len(s)) for _, item := range s { out = append(out, *item) } return out } // StringMapToStringPtrMap converts a map of strings to a map of string pointers. func StringMapToStringPtrMap(m map[string]string) map[string]*string { // Preserve nil in case it matters. if m == nil { return nil } out := make(map[string]*string, len(m)) for key, val := range m { out[key] = Ptr(val) } return out } // StringPtrMapToStringMap converts a map of string pointers to a map of strings. func StringPtrMapToStringMap(m map[string]*string) map[string]string { // Preserve nil in case it matters. if m == nil { return nil } out := make(map[string]string, len(m)) for key, val := range m { if val != nil { out[key] = *val } } return out } // MergeStringPtrMap merges a map of string pointers into a map of strings // following the rules of JSON merge-patch (RFC 7396). In particular, if a // key in src has a nil value, that entry is deleted from dst. The function // takes a pointer to the dst map in case the dst map is nil and needs to be // initialized. func MergeStringPtrMap(src map[string]*string, dst *map[string]string) { if src != nil && dst != nil { for key, val := range src { if val == nil { delete(*dst, key) } else { if *dst == nil { *dst = make(map[string]string) } (*dst)[key] = *val } } } }