1 // 2 // Copyright 2022 The Sigstore 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 package ntpmonitor 17 18 import ( 19 "math/rand" 20 ) 21 22 // RandomChoice returns a random selection of n items from the slice s. 23 // The choice is made using a PSEUDO RANDOM selection. 24 // If n is greater than len(s), an empty slice is returned. 25 func RandomChoice[T any](s []T, n int, r *rand.Rand) []T { 26 if n > len(s) || n < 1 { 27 return []T{} 28 } 29 30 if n == len(s) { 31 return s 32 } 33 34 var indices = make([]int, len(s)) 35 var result = make([]T, 0, n) 36 for i := range s { 37 indices[i] = i 38 } 39 40 for { 41 // The use of deterministic (pseudo) random generators are 42 // ok for this use-case. 43 //nolint:gosec 44 i := r.Intn(len(indices)) 45 46 result = append(result, s[indices[i]]) 47 if len(result) == n { 48 break 49 } 50 51 indices = append(indices[:i], indices[i+1:]...) 52 } 53 54 return result 55 } 56