github.com/influx6/npkg@v0.8.8/nbag/nbag.go (about)

     1  package nbag
     2  
     3  import (
     4  	"context"
     5  	"sync"
     6  	"time"
     7  )
     8  
     9  // Fields defines a map of key:value pairs.
    10  type Fields map[interface{}]interface{}
    11  
    12  // Getter defines a series of Get methods for which values will be retrieved with.
    13  type Getter interface {
    14  	GetInt(interface{}) int
    15  	GetBool(interface{}) bool
    16  	GetInt8(interface{}) int8
    17  	GetInt16(interface{}) int16
    18  	GetInt32(interface{}) int32
    19  	GetInt64(interface{}) int64
    20  	Get(interface{}) interface{}
    21  	GetString(interface{}) string
    22  	GetFloat32(interface{}) float32
    23  	GetFloat64(interface{}) float64
    24  	GetDuration(interface{}) time.Duration
    25  }
    26  
    27  // ValueBag defines a context for holding values to be shared across processes..
    28  type ValueBag interface {
    29  	Getter
    30  
    31  	// Set adds a key-value pair into the bag.
    32  	Set(key, value interface{})
    33  
    34  	// WithValue returns a new context then adds the key and value pair into the
    35  	// context's store.
    36  	WithValue(key interface{}, value interface{}) ValueBag
    37  }
    38  
    39  // vbag defines a struct for bundling a context against specific
    40  // use cases with a explicitly set duration which clears all its internal
    41  // data after the giving period.
    42  type vbag struct {
    43  	ml     sync.RWMutex
    44  	fields map[interface{}]interface{}
    45  }
    46  
    47  // ValueBagFrom adds giving key-value pairs into the bag.
    48  func ValueBagFrom(fields map[interface{}]interface{}) ValueBag {
    49  	return &vbag{fields: fields}
    50  }
    51  
    52  // NewValueBag returns a new context object that meets the Context interface.
    53  func NewValueBag() ValueBag {
    54  	return &vbag{
    55  		fields: map[interface{}]interface{}{},
    56  	}
    57  }
    58  
    59  // Set adds given value into context.
    60  func (c *vbag) Set(key, value interface{}) {
    61  	c.ml.Lock()
    62  	defer c.ml.Unlock()
    63  	c.fields[key] = value
    64  }
    65  
    66  // WithValue returns a new context based on the previos one.
    67  func (c *vbag) WithValue(key, value interface{}) ValueBag {
    68  	c.ml.RLock()
    69  	defer c.ml.RUnlock()
    70  
    71  	fields := make(map[interface{}]interface{})
    72  	for k, v := range c.fields {
    73  		fields[k] = v
    74  	}
    75  
    76  	fields[key] = value
    77  	return ValueBagFrom(fields)
    78  }
    79  
    80  // Deadline returns giving time when context is expected to be canceled.
    81  func (c *vbag) Deadline() time.Time {
    82  	return time.Time{}
    83  }
    84  
    85  // GetDuration returns the duration value of a key if it exists.
    86  func (c *vbag) GetDuration(key interface{}) time.Duration {
    87  	val, found := c.get(key)
    88  	if !found {
    89  		return 0
    90  	}
    91  
    92  	if dval, ok := val.(time.Duration); ok {
    93  		return dval
    94  	}
    95  
    96  	if dval, ok := val.(int64); ok {
    97  		return time.Duration(dval)
    98  	}
    99  
   100  	if sval, ok := val.(string); ok {
   101  		if dur, err := time.ParseDuration(sval); err == nil {
   102  			return dur
   103  		}
   104  	}
   105  
   106  	return 0
   107  }
   108  
   109  // GetBool returns the bool value of a key if it exists.
   110  func (c *vbag) GetBool(key interface{}) bool {
   111  	val, found := c.get(key)
   112  	if !found {
   113  		return false
   114  	}
   115  
   116  	return val.(bool)
   117  
   118  }
   119  
   120  // GetFloat64 returns the float64 value of a key if it exists.
   121  func (c *vbag) GetFloat64(key interface{}) float64 {
   122  	val, found := c.get(key)
   123  	if !found {
   124  		return 0
   125  	}
   126  
   127  	return val.(float64)
   128  
   129  }
   130  
   131  // GetFloat32 returns the float32 value of a key if it exists.
   132  func (c *vbag) GetFloat32(key interface{}) float32 {
   133  	val, found := c.get(key)
   134  	if !found {
   135  		return 0
   136  	}
   137  
   138  	return val.(float32)
   139  
   140  }
   141  
   142  // GetInt8 returns the int8 value of a key if it exists.
   143  func (c *vbag) GetInt8(key interface{}) int8 {
   144  	val, found := c.get(key)
   145  	if !found {
   146  		return 0
   147  	}
   148  
   149  	return val.(int8)
   150  
   151  }
   152  
   153  // GetInt16 returns the int16 value of a key if it exists.
   154  func (c *vbag) GetInt16(key interface{}) int16 {
   155  	val, found := c.get(key)
   156  	if !found {
   157  		return 0
   158  	}
   159  
   160  	return val.(int16)
   161  
   162  }
   163  
   164  // GetInt64 returns the value type value of a key if it exists.
   165  func (c *vbag) GetInt64(key interface{}) int64 {
   166  	val, found := c.get(key)
   167  	if !found {
   168  		return 0
   169  	}
   170  
   171  	return val.(int64)
   172  
   173  }
   174  
   175  // GetInt32 returns the value type value of a key if it exists.
   176  func (c *vbag) GetInt32(key interface{}) int32 {
   177  	val, found := c.get(key)
   178  	if !found {
   179  		return 0
   180  	}
   181  
   182  	return val.(int32)
   183  
   184  }
   185  
   186  // GetInt returns the value type value of a key if it exists.
   187  func (c *vbag) GetInt(key interface{}) int {
   188  	val, found := c.get(key)
   189  	if !found {
   190  		return 0
   191  	}
   192  
   193  	return val.(int)
   194  
   195  }
   196  
   197  // GetString returns the value type value of a key if it exists.
   198  func (c *vbag) GetString(key interface{}) string {
   199  	val, found := c.get(key)
   200  	if !found {
   201  		return ""
   202  	}
   203  
   204  	return val.(string)
   205  
   206  }
   207  
   208  // Get returns the value of a key if it exists.
   209  func (c *vbag) Get(key interface{}) (value interface{}) {
   210  	item, _ := c.get(key)
   211  	return item
   212  }
   213  
   214  // Get returns the value of a key if it exists.
   215  func (c *vbag) get(key interface{}) (value interface{}, found bool) {
   216  	c.ml.RLock()
   217  	defer c.ml.RUnlock()
   218  
   219  	item, ok := c.fields[key]
   220  	return item, ok
   221  }
   222  
   223  //==============================================================================
   224  
   225  // googleContext implements a decorator for googles context package.
   226  type googleContext struct {
   227  	context.Context
   228  }
   229  
   230  // FromContext returns a new context object that meets the Context interface.
   231  func FromContext(ctx context.Context) *googleContext {
   232  	var gc googleContext
   233  	gc.Context = ctx
   234  	return &gc
   235  }
   236  
   237  // GetDuration returns the giving value for the provided key if it exists else nil.
   238  func (g *googleContext) GetDuration(key interface{}) time.Duration {
   239  	val := g.Context.Value(key)
   240  	if val == nil {
   241  		return 0
   242  	}
   243  
   244  	if dval, ok := val.(time.Duration); ok {
   245  		return dval
   246  	}
   247  
   248  	if dval, ok := val.(int64); ok {
   249  		return time.Duration(dval)
   250  	}
   251  
   252  	if sval, ok := val.(string); ok {
   253  		if dur, err := time.ParseDuration(sval); err == nil {
   254  			return dur
   255  		}
   256  	}
   257  
   258  	return 0
   259  }
   260  
   261  // Get returns the giving value for the provided key if it exists else nil.
   262  func (g *googleContext) Get(key interface{}) interface{} {
   263  	val := g.Context.Value(key)
   264  	if val == nil {
   265  		return val
   266  	}
   267  
   268  	return val
   269  }
   270  
   271  // GetBool returns the value type value of a key if it exists.
   272  func (g *googleContext) GetBool(key interface{}) bool {
   273  	return g.Get(key).(bool)
   274  }
   275  
   276  // GetFloat64 returns the value type value of a key if it exists.
   277  func (g *googleContext) GetFloat64(key interface{}) float64 {
   278  	return g.Get(key).(float64)
   279  
   280  }
   281  
   282  // GetFloat32 returns the value type value of a key if it exists.
   283  func (g *googleContext) GetFloat32(key interface{}) float32 {
   284  	return g.Get(key).(float32)
   285  }
   286  
   287  // GetInt8 returns the value type value of a key if it exists.
   288  func (g *googleContext) GetInt8(key interface{}) int8 {
   289  	return g.Get(key).(int8)
   290  }
   291  
   292  // GetInt16 returns the value type value of a key if it exists.
   293  func (g *googleContext) GetInt16(key interface{}) int16 {
   294  	return g.Get(key).(int16)
   295  }
   296  
   297  // GetInt64 returns the value type value of a key if it exists.
   298  func (g *googleContext) GetInt64(key interface{}) int64 {
   299  	return g.Get(key).(int64)
   300  }
   301  
   302  // GetInt32 returns the value type value of a key if it exists.
   303  func (g *googleContext) GetInt32(key interface{}) int32 {
   304  	return g.Get(key).(int32)
   305  }
   306  
   307  // GetInt returns the value type value of a key if it exists.
   308  func (g *googleContext) GetInt(key interface{}) int {
   309  	return g.Get(key).(int)
   310  }
   311  
   312  // GetString returns the value type value of a key if it exists.
   313  func (g *googleContext) GetString(key interface{}) string {
   314  	return g.Get(key).(string)
   315  }
   316  
   317  //==============================================================================
   318  
   319  // Pair defines a struct for storing a linked pair of key and values.
   320  type Pair struct {
   321  	prev  *Pair
   322  	key   interface{}
   323  	value interface{}
   324  }
   325  
   326  // NewPair returns a a key-value pair chain for setting fields.
   327  func NewPair(key, value interface{}) *Pair {
   328  	return &Pair{
   329  		key:   key,
   330  		value: value,
   331  	}
   332  }
   333  
   334  // Append returns a new Pair with the giving key and with the provded Pair set as
   335  // it's previous link.
   336  func Append(p *Pair, key, value interface{}) *Pair {
   337  	return p.Append(key, value)
   338  }
   339  
   340  // Fields returns all internal pair data as a map.
   341  func (p *Pair) Fields() Fields {
   342  	var f Fields
   343  
   344  	if p.prev == nil {
   345  		f = make(Fields)
   346  		f[p.key] = p.value
   347  		return f
   348  	}
   349  
   350  	f = p.prev.Fields()
   351  
   352  	if p.key != "" {
   353  		f[p.key] = p.value
   354  	}
   355  
   356  	return f
   357  }
   358  
   359  // Append returns a new pair with the giving key and value and its previous
   360  // set to this pair.
   361  func (p *Pair) Append(key, val interface{}) *Pair {
   362  	return &Pair{
   363  		prev:  p,
   364  		key:   key,
   365  		value: val,
   366  	}
   367  }
   368  
   369  // RemoveAll sets all key-value pairs to nil for all connected pair, till it reaches
   370  // the root.
   371  func (p *Pair) RemoveAll() {
   372  	p.key = nil
   373  	p.value = nil
   374  
   375  	if p.prev != nil {
   376  		p.prev.RemoveAll()
   377  	}
   378  }
   379  
   380  // Root returns the root Pair in the chain which links all pairs together.
   381  func (p *Pair) Root() *Pair {
   382  	if p.prev == nil {
   383  		return p
   384  	}
   385  
   386  	return p.prev.Root()
   387  }
   388  
   389  // GetDuration returns the duration value of a key if it exists.
   390  func (p *Pair) GetDuration(key interface{}) time.Duration {
   391  	val, found := p.Get(key)
   392  	if !found {
   393  		return 0
   394  	}
   395  
   396  	if dval, ok := val.(time.Duration); ok {
   397  		return dval
   398  	}
   399  
   400  	if dval, ok := val.(int64); ok {
   401  		return time.Duration(dval)
   402  	}
   403  
   404  	if sval, ok := val.(string); ok {
   405  		if dur, err := time.ParseDuration(sval); err == nil {
   406  			return dur
   407  		}
   408  	}
   409  
   410  	return 0
   411  }
   412  
   413  // GetBool returns the bool value of a key if it exists.
   414  func (p *Pair) GetBool(key interface{}) bool {
   415  	val, found := p.Get(key)
   416  	if !found {
   417  		return false
   418  	}
   419  
   420  	return val.(bool)
   421  
   422  }
   423  
   424  // GetFloat64 returns the float64 value of a key if it exists.
   425  func (p *Pair) GetFloat64(key interface{}) float64 {
   426  	val, found := p.Get(key)
   427  	if !found {
   428  		return 0
   429  	}
   430  
   431  	return val.(float64)
   432  
   433  }
   434  
   435  // GetFloat32 returns the float32 value of a key if it exists.
   436  func (p *Pair) GetFloat32(key interface{}) float32 {
   437  	val, found := p.Get(key)
   438  	if !found {
   439  		return 0
   440  	}
   441  
   442  	return val.(float32)
   443  
   444  }
   445  
   446  // GetInt8 returns the int8 value of a key if it exists.
   447  func (p *Pair) GetInt8(key interface{}) int8 {
   448  	val, found := p.Get(key)
   449  	if !found {
   450  		return 0
   451  	}
   452  
   453  	return val.(int8)
   454  
   455  }
   456  
   457  // GetInt16 returns the int16 value of a key if it exists.
   458  func (p *Pair) GetInt16(key interface{}) int16 {
   459  	val, found := p.Get(key)
   460  	if !found {
   461  		return 0
   462  	}
   463  
   464  	return val.(int16)
   465  
   466  }
   467  
   468  // GetInt64 returns the value type value of a key if it exists.
   469  func (p *Pair) GetInt64(key interface{}) int64 {
   470  	val, found := p.Get(key)
   471  	if !found {
   472  		return 0
   473  	}
   474  
   475  	return val.(int64)
   476  
   477  }
   478  
   479  // GetInt32 returns the value type value of a key if it exists.
   480  func (p *Pair) GetInt32(key interface{}) int32 {
   481  	val, found := p.Get(key)
   482  	if !found {
   483  		return 0
   484  	}
   485  
   486  	return val.(int32)
   487  
   488  }
   489  
   490  // GetInt returns the value type value of a key if it exists.
   491  func (p *Pair) GetInt(key interface{}) int {
   492  	val, found := p.Get(key)
   493  	if !found {
   494  		return 0
   495  	}
   496  
   497  	return val.(int)
   498  
   499  }
   500  
   501  // GetString returns the value type value of a key if it exists.
   502  func (p *Pair) GetString(key interface{}) string {
   503  	val, found := p.Get(key)
   504  	if !found {
   505  		return ""
   506  	}
   507  
   508  	return val.(string)
   509  
   510  }
   511  
   512  // Get returns the value of a key if it exists.
   513  func (p *Pair) Get(key interface{}) (interface{}, bool) {
   514  	if p == nil {
   515  		return nil, false
   516  	}
   517  
   518  	if p.key == key {
   519  		return p.value, true
   520  	}
   521  
   522  	if p.prev == nil {
   523  		return nil, false
   524  	}
   525  
   526  	return p.prev.Get(key)
   527  }