github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/grpc/attributes/attributes.go (about)

     1  /*
     2   *
     3   * Copyright 2019 gRPC authors.
     4   *
     5   * Licensed under the Apache License, Version 2.0 (the "License");
     6   * you may not use this file except in compliance with the License.
     7   * You may obtain a copy of the License at
     8   *
     9   *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   *
    17   */
    18  
    19  // Package attributes defines a generic key/value store used in various gRPC
    20  // components.
    21  //
    22  // Experimental
    23  //
    24  // Notice: This package is EXPERIMENTAL and may be changed or removed in a
    25  // later release.
    26  package attributes
    27  
    28  // Attributes is an immutable struct for storing and retrieving generic
    29  // key/value pairs.  Keys must be hashable, and users should define their own
    30  // types for keys.  Values should not be modified after they are added to an
    31  // Attributes or if they were received from one.  If values implement 'Equal(o
    32  // interface{}) bool', it will be called by (*Attributes).Equal to determine
    33  // whether two values with the same key should be considered equal.
    34  type Attributes struct {
    35  	m map[interface{}]interface{}
    36  }
    37  
    38  // New returns a new Attributes containing the key/value pair.
    39  func New(key, value interface{}) *Attributes {
    40  	return &Attributes{m: map[interface{}]interface{}{key: value}}
    41  }
    42  
    43  // WithValue returns a new Attributes containing the previous keys and values
    44  // and the new key/value pair.  If the same key appears multiple times, the
    45  // last value overwrites all previous values for that key.  To remove an
    46  // existing key, use a nil value.  value should not be modified later.
    47  func (a *Attributes) WithValue(key, value interface{}) *Attributes {
    48  	if a == nil {
    49  		return New(key, value)
    50  	}
    51  	n := &Attributes{m: make(map[interface{}]interface{}, len(a.m)+1)}
    52  	for k, v := range a.m {
    53  		n.m[k] = v
    54  	}
    55  	n.m[key] = value
    56  	return n
    57  }
    58  
    59  // Value returns the value associated with these attributes for key, or nil if
    60  // no value is associated with key.  The returned value should not be modified.
    61  func (a *Attributes) Value(key interface{}) interface{} {
    62  	if a == nil {
    63  		return nil
    64  	}
    65  	return a.m[key]
    66  }
    67  
    68  // Equal returns whether a and o are equivalent.  If 'Equal(o interface{})
    69  // bool' is implemented for a value in the attributes, it is called to
    70  // determine if the value matches the one stored in the other attributes.  If
    71  // Equal is not implemented, standard equality is used to determine if the two
    72  // values are equal. Note that some types (e.g. maps) aren't comparable by
    73  // default, so they must be wrapped in a struct, or in an alias type, with Equal
    74  // defined.
    75  func (a *Attributes) Equal(o *Attributes) bool {
    76  	if a == nil && o == nil {
    77  		return true
    78  	}
    79  	if a == nil || o == nil {
    80  		return false
    81  	}
    82  	if len(a.m) != len(o.m) {
    83  		return false
    84  	}
    85  	for k, v := range a.m {
    86  		ov, ok := o.m[k]
    87  		if !ok {
    88  			// o missing element of a
    89  			return false
    90  		}
    91  		if eq, ok := v.(interface{ Equal(o interface{}) bool }); ok {
    92  			if !eq.Equal(ov) {
    93  				return false
    94  			}
    95  		} else if v != ov {
    96  			// Fallback to a standard equality check if Value is unimplemented.
    97  			return false
    98  		}
    99  	}
   100  	return true
   101  }