github.com/aaabigfish/gopkg@v1.1.0/cloud/metainfo/utils.go (about)

     1  // Copyright 2021 ByteDance Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package metainfo
    16  
    17  import (
    18  	"context"
    19  	"strings"
    20  )
    21  
    22  // HasMetaInfo detects whether the given context contains metainfo.
    23  func HasMetaInfo(ctx context.Context) bool {
    24  	return getNode(ctx) != nil
    25  }
    26  
    27  // SetMetaInfoFromMap retrieves metainfo key-value pairs from the given map and sets then into the context.
    28  // Only those keys with prefixes defined in this module would be used.
    29  // If the context has been carrying metanifo pairs, they will be merged as a basis.
    30  func SetMetaInfoFromMap(ctx context.Context, m map[string]string) context.Context {
    31  	if ctx == nil {
    32  		return nil
    33  	}
    34  
    35  	if len(m) == 0 {
    36  		return ctx
    37  	}
    38  
    39  	var mv *mapView
    40  	if x := getNode(ctx); x != nil {
    41  		mv = x.mapView()
    42  	} else {
    43  		mv = newMapView()
    44  	}
    45  
    46  	for k, v := range m {
    47  		if len(k) == 0 || len(v) == 0 {
    48  			continue
    49  		}
    50  
    51  		switch {
    52  		case strings.HasPrefix(k, PrefixTransientUpstream):
    53  			if len(k) > lenPTU { // do not move this condition to the case statement to prevent a PTU matches PT
    54  				mv.stale[k[lenPTU:]] = v
    55  			}
    56  		case strings.HasPrefix(k, PrefixTransient):
    57  			if len(k) > lenPT {
    58  				mv.transient[k[lenPT:]] = v
    59  			}
    60  		case strings.HasPrefix(k, PrefixPersistent):
    61  			if len(k) > lenPP {
    62  				mv.persistent[k[lenPP:]] = v
    63  			}
    64  		}
    65  	}
    66  
    67  	if mv.size() == 0 {
    68  		// TODO: remove this?
    69  		return ctx
    70  	}
    71  
    72  	return withNode(ctx, mv.toNode())
    73  }
    74  
    75  // SaveMetaInfoToMap set key-value pairs from ctx to m while filtering out transient-upstream data.
    76  func SaveMetaInfoToMap(ctx context.Context, m map[string]string) {
    77  	if ctx == nil || m == nil {
    78  		return
    79  	}
    80  	ctx = TransferForward(ctx)
    81  	for k, v := range GetAllValues(ctx) {
    82  		m[PrefixTransient+k] = v
    83  	}
    84  	for k, v := range GetAllPersistentValues(ctx) {
    85  		m[PrefixPersistent+k] = v
    86  	}
    87  }
    88  
    89  // sliceToMap converts a kv slice to map. If the slice is empty, an empty map will be returned instead of nil.
    90  func sliceToMap(slice []kv) (m map[string]string) {
    91  	if size := len(slice); size == 0 {
    92  		m = make(map[string]string)
    93  	} else {
    94  		m = make(map[string]string, size)
    95  	}
    96  	for _, kv := range slice {
    97  		m[kv.key] = kv.val
    98  	}
    99  	return
   100  }
   101  
   102  // mapToSlice converts a map to a kv slice. If the map is empty, the return value will be nil.
   103  func mapToSlice(kvs map[string]string) (slice []kv) {
   104  	size := len(kvs)
   105  	if size == 0 {
   106  		return
   107  	}
   108  	slice = make([]kv, 0, size)
   109  	for k, v := range kvs {
   110  		slice = append(slice, kv{key: k, val: v})
   111  	}
   112  	return
   113  }