github.com/gravitational/teleport/api@v0.0.0-20240507183017-3110591cbafc/utils/strings.go (about)

     1  /*
     2  Copyright 2021 Gravitational, Inc.
     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 utils
    18  
    19  import (
    20  	"encoding/json"
    21  	"strings"
    22  
    23  	"github.com/gravitational/trace"
    24  )
    25  
    26  // Strings is a list of string that can unmarshal from list of strings
    27  // or a scalar string from scalar yaml or json property
    28  type Strings []string
    29  
    30  // UnmarshalJSON unmarshals scalar string or strings slice to Strings
    31  func (s *Strings) UnmarshalJSON(data []byte) error {
    32  	if len(data) == 0 {
    33  		return nil
    34  	}
    35  	var stringVar string
    36  	if err := json.Unmarshal(data, &stringVar); err == nil {
    37  		*s = []string{stringVar}
    38  		return nil
    39  	}
    40  	var stringsVar []string
    41  	if err := json.Unmarshal(data, &stringsVar); err != nil {
    42  		return trace.Wrap(err)
    43  	}
    44  	*s = stringsVar
    45  	return nil
    46  }
    47  
    48  // UnmarshalYAML is used to allow Strings to unmarshal from
    49  // scalar string value or from the list
    50  func (s *Strings) UnmarshalYAML(unmarshal func(interface{}) error) error {
    51  	// try unmarshal as string
    52  	var val string
    53  	err := unmarshal(&val)
    54  	if err == nil {
    55  		*s = []string{val}
    56  		return nil
    57  	}
    58  
    59  	// try unmarshal as slice
    60  	var slice []string
    61  	err = unmarshal(&slice)
    62  	if err == nil {
    63  		*s = slice
    64  		return nil
    65  	}
    66  
    67  	return err
    68  }
    69  
    70  // MarshalJSON marshals to scalar value
    71  // if there is only one value in the list
    72  // to list otherwise
    73  func (s Strings) MarshalJSON() ([]byte, error) {
    74  	if len(s) == 1 {
    75  		return json.Marshal(s[0])
    76  	}
    77  	return json.Marshal([]string(s))
    78  }
    79  
    80  // MarshalYAML marshals to scalar value
    81  // if there is only one value in the list,
    82  // marshals to list otherwise
    83  func (s Strings) MarshalYAML() (interface{}, error) {
    84  	if len(s) == 1 {
    85  		return s[0], nil
    86  	}
    87  	return []string(s), nil
    88  }
    89  
    90  // CopyStrings makes a deep copy of the passed in string slice and returns
    91  // the copy.
    92  func CopyStrings(in []string) []string {
    93  	if in == nil {
    94  		return nil
    95  	}
    96  
    97  	out := make([]string, len(in))
    98  	copy(out, in)
    99  
   100  	return out
   101  }
   102  
   103  // MapToStrings collects keys and values of a map into a slice of strings.
   104  func MapToStrings(m map[string]string) []string {
   105  	s := make([]string, 0, len(m)*2)
   106  	for key, value := range m {
   107  		s = append(s, key, value)
   108  	}
   109  	return s
   110  }
   111  
   112  // ToLowerStrings lower cases each string in a slice.
   113  func ToLowerStrings(strs []string) []string {
   114  	lowerCasedStrs := make([]string, len(strs))
   115  	for i, s := range strs {
   116  		lowerCasedStrs[i] = strings.ToLower(s)
   117  	}
   118  
   119  	return lowerCasedStrs
   120  }