mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-03-09 08:59:30 +00:00
Several packages are only used while running the e2e suite. These packages are less important to update, as the they can not influence the final executable that is part of the Ceph-CSI container-image. By moving these dependencies out of the main Ceph-CSI go.mod, it is easier to identify if a reported CVE affects Ceph-CSI, or only the testing (like most of the Kubernetes CVEs). Signed-off-by: Niels de Vos <ndevos@ibm.com>
365 lines
8.7 KiB
Go
365 lines
8.7 KiB
Go
// Copyright 2015 go-swagger maintainers
|
|
//
|
|
// 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 swag
|
|
|
|
import (
|
|
"reflect"
|
|
"strings"
|
|
"unicode"
|
|
"unicode/utf8"
|
|
)
|
|
|
|
// GoNamePrefixFunc sets an optional rule to prefix go names
|
|
// which do not start with a letter.
|
|
//
|
|
// The prefix function is assumed to return a string that starts with an upper case letter.
|
|
//
|
|
// e.g. to help convert "123" into "{prefix}123"
|
|
//
|
|
// The default is to prefix with "X"
|
|
var GoNamePrefixFunc func(string) string
|
|
|
|
func prefixFunc(name, in string) string {
|
|
if GoNamePrefixFunc == nil {
|
|
return "X" + in
|
|
}
|
|
|
|
return GoNamePrefixFunc(name) + in
|
|
}
|
|
|
|
const (
|
|
// collectionFormatComma = "csv"
|
|
collectionFormatSpace = "ssv"
|
|
collectionFormatTab = "tsv"
|
|
collectionFormatPipe = "pipes"
|
|
collectionFormatMulti = "multi"
|
|
)
|
|
|
|
// JoinByFormat joins a string array by a known format (e.g. swagger's collectionFormat attribute):
|
|
//
|
|
// ssv: space separated value
|
|
// tsv: tab separated value
|
|
// pipes: pipe (|) separated value
|
|
// csv: comma separated value (default)
|
|
func JoinByFormat(data []string, format string) []string {
|
|
if len(data) == 0 {
|
|
return data
|
|
}
|
|
var sep string
|
|
switch format {
|
|
case collectionFormatSpace:
|
|
sep = " "
|
|
case collectionFormatTab:
|
|
sep = "\t"
|
|
case collectionFormatPipe:
|
|
sep = "|"
|
|
case collectionFormatMulti:
|
|
return data
|
|
default:
|
|
sep = ","
|
|
}
|
|
return []string{strings.Join(data, sep)}
|
|
}
|
|
|
|
// SplitByFormat splits a string by a known format:
|
|
//
|
|
// ssv: space separated value
|
|
// tsv: tab separated value
|
|
// pipes: pipe (|) separated value
|
|
// csv: comma separated value (default)
|
|
func SplitByFormat(data, format string) []string {
|
|
if data == "" {
|
|
return nil
|
|
}
|
|
var sep string
|
|
switch format {
|
|
case collectionFormatSpace:
|
|
sep = " "
|
|
case collectionFormatTab:
|
|
sep = "\t"
|
|
case collectionFormatPipe:
|
|
sep = "|"
|
|
case collectionFormatMulti:
|
|
return nil
|
|
default:
|
|
sep = ","
|
|
}
|
|
var result []string
|
|
for _, s := range strings.Split(data, sep) {
|
|
if ts := strings.TrimSpace(s); ts != "" {
|
|
result = append(result, ts)
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
// Removes leading whitespaces
|
|
func trim(str string) string {
|
|
return strings.TrimSpace(str)
|
|
}
|
|
|
|
// Shortcut to strings.ToUpper()
|
|
func upper(str string) string {
|
|
return strings.ToUpper(trim(str))
|
|
}
|
|
|
|
// Shortcut to strings.ToLower()
|
|
func lower(str string) string {
|
|
return strings.ToLower(trim(str))
|
|
}
|
|
|
|
// Camelize an uppercased word
|
|
func Camelize(word string) string {
|
|
camelized := poolOfBuffers.BorrowBuffer(len(word))
|
|
defer func() {
|
|
poolOfBuffers.RedeemBuffer(camelized)
|
|
}()
|
|
|
|
for pos, ru := range []rune(word) {
|
|
if pos > 0 {
|
|
camelized.WriteRune(unicode.ToLower(ru))
|
|
} else {
|
|
camelized.WriteRune(unicode.ToUpper(ru))
|
|
}
|
|
}
|
|
return camelized.String()
|
|
}
|
|
|
|
// ToFileName lowercases and underscores a go type name
|
|
func ToFileName(name string) string {
|
|
in := split(name)
|
|
out := make([]string, 0, len(in))
|
|
|
|
for _, w := range in {
|
|
out = append(out, lower(w))
|
|
}
|
|
|
|
return strings.Join(out, "_")
|
|
}
|
|
|
|
// ToCommandName lowercases and underscores a go type name
|
|
func ToCommandName(name string) string {
|
|
in := split(name)
|
|
out := make([]string, 0, len(in))
|
|
|
|
for _, w := range in {
|
|
out = append(out, lower(w))
|
|
}
|
|
return strings.Join(out, "-")
|
|
}
|
|
|
|
// ToHumanNameLower represents a code name as a human series of words
|
|
func ToHumanNameLower(name string) string {
|
|
s := poolOfSplitters.BorrowSplitter(withPostSplitInitialismCheck)
|
|
in := s.split(name)
|
|
poolOfSplitters.RedeemSplitter(s)
|
|
out := make([]string, 0, len(*in))
|
|
|
|
for _, w := range *in {
|
|
if !w.IsInitialism() {
|
|
out = append(out, lower(w.GetOriginal()))
|
|
} else {
|
|
out = append(out, trim(w.GetOriginal()))
|
|
}
|
|
}
|
|
poolOfLexems.RedeemLexems(in)
|
|
|
|
return strings.Join(out, " ")
|
|
}
|
|
|
|
// ToHumanNameTitle represents a code name as a human series of words with the first letters titleized
|
|
func ToHumanNameTitle(name string) string {
|
|
s := poolOfSplitters.BorrowSplitter(withPostSplitInitialismCheck)
|
|
in := s.split(name)
|
|
poolOfSplitters.RedeemSplitter(s)
|
|
|
|
out := make([]string, 0, len(*in))
|
|
for _, w := range *in {
|
|
original := trim(w.GetOriginal())
|
|
if !w.IsInitialism() {
|
|
out = append(out, Camelize(original))
|
|
} else {
|
|
out = append(out, original)
|
|
}
|
|
}
|
|
poolOfLexems.RedeemLexems(in)
|
|
|
|
return strings.Join(out, " ")
|
|
}
|
|
|
|
// ToJSONName camelcases a name which can be underscored or pascal cased
|
|
func ToJSONName(name string) string {
|
|
in := split(name)
|
|
out := make([]string, 0, len(in))
|
|
|
|
for i, w := range in {
|
|
if i == 0 {
|
|
out = append(out, lower(w))
|
|
continue
|
|
}
|
|
out = append(out, Camelize(trim(w)))
|
|
}
|
|
return strings.Join(out, "")
|
|
}
|
|
|
|
// ToVarName camelcases a name which can be underscored or pascal cased
|
|
func ToVarName(name string) string {
|
|
res := ToGoName(name)
|
|
if isInitialism(res) {
|
|
return lower(res)
|
|
}
|
|
if len(res) <= 1 {
|
|
return lower(res)
|
|
}
|
|
return lower(res[:1]) + res[1:]
|
|
}
|
|
|
|
// ToGoName translates a swagger name which can be underscored or camel cased to a name that golint likes
|
|
func ToGoName(name string) string {
|
|
s := poolOfSplitters.BorrowSplitter(withPostSplitInitialismCheck)
|
|
lexems := s.split(name)
|
|
poolOfSplitters.RedeemSplitter(s)
|
|
defer func() {
|
|
poolOfLexems.RedeemLexems(lexems)
|
|
}()
|
|
lexemes := *lexems
|
|
|
|
if len(lexemes) == 0 {
|
|
return ""
|
|
}
|
|
|
|
result := poolOfBuffers.BorrowBuffer(len(name))
|
|
defer func() {
|
|
poolOfBuffers.RedeemBuffer(result)
|
|
}()
|
|
|
|
// check if not starting with a letter, upper case
|
|
firstPart := lexemes[0].GetUnsafeGoName()
|
|
if lexemes[0].IsInitialism() {
|
|
firstPart = upper(firstPart)
|
|
}
|
|
|
|
if c := firstPart[0]; c < utf8.RuneSelf {
|
|
// ASCII
|
|
switch {
|
|
case 'A' <= c && c <= 'Z':
|
|
result.WriteString(firstPart)
|
|
case 'a' <= c && c <= 'z':
|
|
result.WriteByte(c - 'a' + 'A')
|
|
result.WriteString(firstPart[1:])
|
|
default:
|
|
result.WriteString(prefixFunc(name, firstPart))
|
|
// NOTE: no longer check if prefixFunc returns a string that starts with uppercase:
|
|
// assume this is always the case
|
|
}
|
|
} else {
|
|
// unicode
|
|
firstRune, _ := utf8.DecodeRuneInString(firstPart)
|
|
switch {
|
|
case !unicode.IsLetter(firstRune):
|
|
result.WriteString(prefixFunc(name, firstPart))
|
|
case !unicode.IsUpper(firstRune):
|
|
result.WriteString(prefixFunc(name, firstPart))
|
|
/*
|
|
result.WriteRune(unicode.ToUpper(firstRune))
|
|
result.WriteString(firstPart[offset:])
|
|
*/
|
|
default:
|
|
result.WriteString(firstPart)
|
|
}
|
|
}
|
|
|
|
for _, lexem := range lexemes[1:] {
|
|
goName := lexem.GetUnsafeGoName()
|
|
|
|
// to support old behavior
|
|
if lexem.IsInitialism() {
|
|
goName = upper(goName)
|
|
}
|
|
result.WriteString(goName)
|
|
}
|
|
|
|
return result.String()
|
|
}
|
|
|
|
// ContainsStrings searches a slice of strings for a case-sensitive match
|
|
func ContainsStrings(coll []string, item string) bool {
|
|
for _, a := range coll {
|
|
if a == item {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// ContainsStringsCI searches a slice of strings for a case-insensitive match
|
|
func ContainsStringsCI(coll []string, item string) bool {
|
|
for _, a := range coll {
|
|
if strings.EqualFold(a, item) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
type zeroable interface {
|
|
IsZero() bool
|
|
}
|
|
|
|
// IsZero returns true when the value passed into the function is a zero value.
|
|
// This allows for safer checking of interface values.
|
|
func IsZero(data interface{}) bool {
|
|
v := reflect.ValueOf(data)
|
|
// check for nil data
|
|
switch v.Kind() { //nolint:exhaustive
|
|
case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
|
|
if v.IsNil() {
|
|
return true
|
|
}
|
|
}
|
|
|
|
// check for things that have an IsZero method instead
|
|
if vv, ok := data.(zeroable); ok {
|
|
return vv.IsZero()
|
|
}
|
|
|
|
// continue with slightly more complex reflection
|
|
switch v.Kind() { //nolint:exhaustive
|
|
case reflect.String:
|
|
return v.Len() == 0
|
|
case reflect.Bool:
|
|
return !v.Bool()
|
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
return v.Int() == 0
|
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
|
return v.Uint() == 0
|
|
case reflect.Float32, reflect.Float64:
|
|
return v.Float() == 0
|
|
case reflect.Struct, reflect.Array:
|
|
return reflect.DeepEqual(data, reflect.Zero(v.Type()).Interface())
|
|
case reflect.Invalid:
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
// CommandLineOptionsGroup represents a group of user-defined command line options
|
|
type CommandLineOptionsGroup struct {
|
|
ShortDescription string
|
|
LongDescription string
|
|
Options interface{}
|
|
}
|