gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

attributes.go (3335B)


      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 }