main
Raw Download raw file
  1//go:build linux && !go1.21
  2
  3// Copyright (C) 2024 SUSE LLC. All rights reserved.
  4// Use of this source code is governed by a BSD-style
  5// license that can be found in the LICENSE file.
  6
  7package securejoin
  8
  9import (
 10	"sync"
 11)
 12
 13// These are very minimal implementations of functions that appear in Go 1.21's
 14// stdlib, included so that we can build on older Go versions. Most are
 15// borrowed directly from the stdlib, and a few are modified to be "obviously
 16// correct" without needing to copy too many other helpers.
 17
 18// clearSlice is equivalent to the builtin clear from Go 1.21.
 19// Copied from the Go 1.24 stdlib implementation.
 20func clearSlice[S ~[]E, E any](slice S) {
 21	var zero E
 22	for i := range slice {
 23		slice[i] = zero
 24	}
 25}
 26
 27// Copied from the Go 1.24 stdlib implementation.
 28func slices_IndexFunc[S ~[]E, E any](s S, f func(E) bool) int {
 29	for i := range s {
 30		if f(s[i]) {
 31			return i
 32		}
 33	}
 34	return -1
 35}
 36
 37// Copied from the Go 1.24 stdlib implementation.
 38func slices_DeleteFunc[S ~[]E, E any](s S, del func(E) bool) S {
 39	i := slices_IndexFunc(s, del)
 40	if i == -1 {
 41		return s
 42	}
 43	// Don't start copying elements until we find one to delete.
 44	for j := i + 1; j < len(s); j++ {
 45		if v := s[j]; !del(v) {
 46			s[i] = v
 47			i++
 48		}
 49	}
 50	clearSlice(s[i:]) // zero/nil out the obsolete elements, for GC
 51	return s[:i]
 52}
 53
 54// Similar to the stdlib slices.Contains, except that we don't have
 55// slices.Index so we need to use slices.IndexFunc for this non-Func helper.
 56func slices_Contains[S ~[]E, E comparable](s S, v E) bool {
 57	return slices_IndexFunc(s, func(e E) bool { return e == v }) >= 0
 58}
 59
 60// Copied from the Go 1.24 stdlib implementation.
 61func slices_Clone[S ~[]E, E any](s S) S {
 62	// Preserve nil in case it matters.
 63	if s == nil {
 64		return nil
 65	}
 66	return append(S([]E{}), s...)
 67}
 68
 69// Copied from the Go 1.24 stdlib implementation.
 70func sync_OnceValue[T any](f func() T) func() T {
 71	var (
 72		once   sync.Once
 73		valid  bool
 74		p      any
 75		result T
 76	)
 77	g := func() {
 78		defer func() {
 79			p = recover()
 80			if !valid {
 81				panic(p)
 82			}
 83		}()
 84		result = f()
 85		f = nil
 86		valid = true
 87	}
 88	return func() T {
 89		once.Do(g)
 90		if !valid {
 91			panic(p)
 92		}
 93		return result
 94	}
 95}
 96
 97// Copied from the Go 1.24 stdlib implementation.
 98func sync_OnceValues[T1, T2 any](f func() (T1, T2)) func() (T1, T2) {
 99	var (
100		once  sync.Once
101		valid bool
102		p     any
103		r1    T1
104		r2    T2
105	)
106	g := func() {
107		defer func() {
108			p = recover()
109			if !valid {
110				panic(p)
111			}
112		}()
113		r1, r2 = f()
114		f = nil
115		valid = true
116	}
117	return func() (T1, T2) {
118		once.Do(g)
119		if !valid {
120			panic(p)
121		}
122		return r1, r2
123	}
124}