github.com/minio/minio@v0.0.0-20240328213742-3f72439b8a27/internal/grid/types.go (about)

     1  // Copyright (c) 2015-2023 MinIO, Inc.
     2  //
     3  // This file is part of MinIO Object Storage stack
     4  //
     5  // This program is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU Affero General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // This program is distributed in the hope that it will be useful
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  // GNU Affero General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Affero General Public License
    16  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17  
    18  package grid
    19  
    20  import (
    21  	"bytes"
    22  	"encoding/json"
    23  	"errors"
    24  	"math"
    25  	"net/url"
    26  	"sort"
    27  	"strings"
    28  	"sync"
    29  
    30  	"github.com/tinylib/msgp/msgp"
    31  )
    32  
    33  // Recycler will override the internal reuse in typed handlers.
    34  // When this is supported, the handler will not do internal pooling of objects,
    35  // call Recycle() when the object is no longer needed.
    36  // The recycler should handle nil pointers.
    37  type Recycler interface {
    38  	Recycle()
    39  }
    40  
    41  // MSS is a map[string]string that can be serialized.
    42  // It is not very efficient, but it is only used for easy parameter passing.
    43  type MSS map[string]string
    44  
    45  // Get returns the value for the given key.
    46  func (m *MSS) Get(key string) string {
    47  	if m == nil {
    48  		return ""
    49  	}
    50  	return (*m)[key]
    51  }
    52  
    53  // Set a key, value pair.
    54  func (m *MSS) Set(key, value string) {
    55  	if m == nil {
    56  		*m = mssPool.Get().(map[string]string)
    57  	}
    58  	(*m)[key] = value
    59  }
    60  
    61  // UnmarshalMsg deserializes m from the provided byte slice and returns the
    62  // remainder of bytes.
    63  func (m *MSS) UnmarshalMsg(bts []byte) (o []byte, err error) {
    64  	if m == nil {
    65  		return bts, errors.New("MSS: UnmarshalMsg on nil pointer")
    66  	}
    67  	if msgp.IsNil(bts) {
    68  		bts = bts[1:]
    69  		*m = nil
    70  		return bts, nil
    71  	}
    72  	var zb0002 uint32
    73  	zb0002, bts, err = msgp.ReadMapHeaderBytes(bts)
    74  	if err != nil {
    75  		err = msgp.WrapError(err, "Values")
    76  		return
    77  	}
    78  	dst := *m
    79  	if dst == nil {
    80  		dst = make(map[string]string, zb0002)
    81  	} else if len(dst) > 0 {
    82  		for key := range dst {
    83  			delete(dst, key)
    84  		}
    85  	}
    86  	for zb0002 > 0 {
    87  		var za0001 string
    88  		var za0002 string
    89  		zb0002--
    90  		za0001, bts, err = msgp.ReadStringBytes(bts)
    91  		if err != nil {
    92  			err = msgp.WrapError(err, "Values")
    93  			return
    94  		}
    95  		za0002, bts, err = msgp.ReadStringBytes(bts)
    96  		if err != nil {
    97  			err = msgp.WrapError(err, "Values", za0001)
    98  			return
    99  		}
   100  		dst[za0001] = za0002
   101  	}
   102  	*m = dst
   103  	return bts, nil
   104  }
   105  
   106  // MarshalMsg appends the bytes representation of b to the provided byte slice.
   107  func (m *MSS) MarshalMsg(bytes []byte) (o []byte, err error) {
   108  	if m == nil || *m == nil {
   109  		return msgp.AppendNil(bytes), nil
   110  	}
   111  	o = msgp.AppendMapHeader(bytes, uint32(len(*m)))
   112  	for za0001, za0002 := range *m {
   113  		o = msgp.AppendString(o, za0001)
   114  		o = msgp.AppendString(o, za0002)
   115  	}
   116  	return o, nil
   117  }
   118  
   119  // Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message.
   120  func (m *MSS) Msgsize() int {
   121  	if m == nil || *m == nil {
   122  		return msgp.NilSize
   123  	}
   124  	s := msgp.MapHeaderSize
   125  	for za0001, za0002 := range *m {
   126  		s += msgp.StringPrefixSize + len(za0001) + msgp.StringPrefixSize + len(za0002)
   127  	}
   128  	return s
   129  }
   130  
   131  // NewMSS returns a new MSS.
   132  func NewMSS() *MSS {
   133  	m := MSS(mssPool.Get().(map[string]string))
   134  	for k := range m {
   135  		delete(m, k)
   136  	}
   137  	return &m
   138  }
   139  
   140  // NewMSSWith returns a new MSS with the given map.
   141  func NewMSSWith(m map[string]string) *MSS {
   142  	m2 := MSS(m)
   143  	return &m2
   144  }
   145  
   146  var mssPool = sync.Pool{
   147  	New: func() interface{} {
   148  		return make(map[string]string, 5)
   149  	},
   150  }
   151  
   152  // Recycle the underlying map.
   153  func (m *MSS) Recycle() {
   154  	if m != nil && *m != nil {
   155  		mssPool.Put(map[string]string(*m))
   156  		*m = nil
   157  	}
   158  }
   159  
   160  // ToQuery constructs a URL query string from the MSS, including "?" if there are any keys.
   161  func (m MSS) ToQuery() string {
   162  	if len(m) == 0 {
   163  		return ""
   164  	}
   165  	var buf strings.Builder
   166  	buf.WriteByte('?')
   167  	keys := make([]string, 0, len(m))
   168  	for k := range m {
   169  		keys = append(keys, k)
   170  	}
   171  	sort.Strings(keys)
   172  	for _, k := range keys {
   173  		v := m[k]
   174  		keyEscaped := url.QueryEscape(k)
   175  		if buf.Len() > 1 {
   176  			buf.WriteByte('&')
   177  		}
   178  		buf.WriteString(keyEscaped)
   179  		buf.WriteByte('=')
   180  		buf.WriteString(url.QueryEscape(v))
   181  	}
   182  	return buf.String()
   183  }
   184  
   185  // NewBytes returns a new Bytes.
   186  // A slice is preallocated.
   187  func NewBytes() *Bytes {
   188  	b := Bytes(GetByteBuffer()[:0])
   189  	return &b
   190  }
   191  
   192  // NewBytesWith returns a new Bytes with the provided content.
   193  // When sent as a parameter, the caller gives up ownership of the byte slice.
   194  // When returned as response, the handler also gives up ownership of the byte slice.
   195  func NewBytesWith(b []byte) *Bytes {
   196  	bb := Bytes(b)
   197  	return &bb
   198  }
   199  
   200  // NewBytesWithCopyOf returns a new byte slice with a copy of the provided content.
   201  func NewBytesWithCopyOf(b []byte) *Bytes {
   202  	if b == nil {
   203  		bb := Bytes(nil)
   204  		return &bb
   205  	}
   206  	if len(b) < maxBufferSize {
   207  		bb := NewBytes()
   208  		*bb = append(*bb, b...)
   209  		return bb
   210  	}
   211  	bb := Bytes(make([]byte, len(b)))
   212  	copy(bb, b)
   213  	return &bb
   214  }
   215  
   216  // Bytes provides a byte slice that can be serialized.
   217  type Bytes []byte
   218  
   219  // UnmarshalMsg deserializes b from the provided byte slice and returns the
   220  // remainder of bytes.
   221  func (b *Bytes) UnmarshalMsg(bytes []byte) ([]byte, error) {
   222  	if b == nil {
   223  		return bytes, errors.New("Bytes: UnmarshalMsg on nil pointer")
   224  	}
   225  	if bytes, err := msgp.ReadNilBytes(bytes); err == nil {
   226  		if *b != nil {
   227  			PutByteBuffer(*b)
   228  		}
   229  		*b = nil
   230  		return bytes, nil
   231  	}
   232  	val, bytes, err := msgp.ReadBytesZC(bytes)
   233  	if err != nil {
   234  		return bytes, err
   235  	}
   236  	if cap(*b) >= len(val) {
   237  		*b = (*b)[:len(val)]
   238  		copy(*b, val)
   239  	} else {
   240  		if cap(*b) == 0 && len(val) <= maxBufferSize {
   241  			*b = GetByteBuffer()[:0]
   242  		} else {
   243  			PutByteBuffer(*b)
   244  			*b = make([]byte, 0, len(val))
   245  		}
   246  		in := *b
   247  		in = append(in[:0], val...)
   248  		*b = in
   249  	}
   250  	return bytes, nil
   251  }
   252  
   253  // MarshalMsg appends the bytes representation of b to the provided byte slice.
   254  func (b *Bytes) MarshalMsg(bytes []byte) ([]byte, error) {
   255  	if b == nil || *b == nil {
   256  		return msgp.AppendNil(bytes), nil
   257  	}
   258  	return msgp.AppendBytes(bytes, *b), nil
   259  }
   260  
   261  // Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message.
   262  func (b *Bytes) Msgsize() int {
   263  	if b == nil || *b == nil {
   264  		return msgp.NilSize
   265  	}
   266  	return msgp.ArrayHeaderSize + len(*b)
   267  }
   268  
   269  // Recycle puts the Bytes back into the pool.
   270  func (b *Bytes) Recycle() {
   271  	if b != nil && *b != nil {
   272  		*b = (*b)[:0]
   273  		PutByteBuffer(*b)
   274  		*b = nil
   275  	}
   276  }
   277  
   278  // URLValues can be used for url.Values.
   279  type URLValues map[string][]string
   280  
   281  var urlValuesPool = sync.Pool{
   282  	New: func() interface{} {
   283  		return make(map[string][]string, 10)
   284  	},
   285  }
   286  
   287  // NewURLValues returns a new URLValues.
   288  func NewURLValues() *URLValues {
   289  	u := URLValues(urlValuesPool.Get().(map[string][]string))
   290  	return &u
   291  }
   292  
   293  // NewURLValuesWith returns a new URLValues with the provided content.
   294  func NewURLValuesWith(values map[string][]string) *URLValues {
   295  	u := URLValues(values)
   296  	return &u
   297  }
   298  
   299  // Values returns the url.Values.
   300  // If u is nil, an empty url.Values is returned.
   301  // The values are a shallow copy of the underlying map.
   302  func (u *URLValues) Values() url.Values {
   303  	if u == nil {
   304  		return url.Values{}
   305  	}
   306  	return url.Values(*u)
   307  }
   308  
   309  // Recycle the underlying map.
   310  func (u *URLValues) Recycle() {
   311  	if *u != nil {
   312  		for key := range *u {
   313  			delete(*u, key)
   314  		}
   315  		val := map[string][]string(*u)
   316  		urlValuesPool.Put(val)
   317  		*u = nil
   318  	}
   319  }
   320  
   321  // MarshalMsg implements msgp.Marshaler
   322  func (u URLValues) MarshalMsg(b []byte) (o []byte, err error) {
   323  	o = msgp.Require(b, u.Msgsize())
   324  	o = msgp.AppendMapHeader(o, uint32(len(u)))
   325  	for zb0006, zb0007 := range u {
   326  		o = msgp.AppendString(o, zb0006)
   327  		o = msgp.AppendArrayHeader(o, uint32(len(zb0007)))
   328  		for zb0008 := range zb0007 {
   329  			o = msgp.AppendString(o, zb0007[zb0008])
   330  		}
   331  	}
   332  	return
   333  }
   334  
   335  // UnmarshalMsg implements msgp.Unmarshaler
   336  func (u *URLValues) UnmarshalMsg(bts []byte) (o []byte, err error) {
   337  	var zb0004 uint32
   338  	zb0004, bts, err = msgp.ReadMapHeaderBytes(bts)
   339  	if err != nil {
   340  		err = msgp.WrapError(err)
   341  		return
   342  	}
   343  	if *u == nil {
   344  		*u = urlValuesPool.Get().(map[string][]string)
   345  	}
   346  	if len(*u) > 0 {
   347  		for key := range *u {
   348  			delete(*u, key)
   349  		}
   350  	}
   351  
   352  	for zb0004 > 0 {
   353  		var zb0001 string
   354  		var zb0002 []string
   355  		zb0004--
   356  		zb0001, bts, err = msgp.ReadStringBytes(bts)
   357  		if err != nil {
   358  			err = msgp.WrapError(err)
   359  			return
   360  		}
   361  		var zb0005 uint32
   362  		zb0005, bts, err = msgp.ReadArrayHeaderBytes(bts)
   363  		if err != nil {
   364  			err = msgp.WrapError(err, zb0001)
   365  			return
   366  		}
   367  		if cap(zb0002) >= int(zb0005) {
   368  			zb0002 = zb0002[:zb0005]
   369  		} else {
   370  			zb0002 = make([]string, zb0005)
   371  		}
   372  		for zb0003 := range zb0002 {
   373  			zb0002[zb0003], bts, err = msgp.ReadStringBytes(bts)
   374  			if err != nil {
   375  				err = msgp.WrapError(err, zb0001, zb0003)
   376  				return
   377  			}
   378  		}
   379  		(*u)[zb0001] = zb0002
   380  	}
   381  	o = bts
   382  	return
   383  }
   384  
   385  // Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
   386  func (u URLValues) Msgsize() (s int) {
   387  	s = msgp.MapHeaderSize
   388  	if u != nil {
   389  		for zb0006, zb0007 := range u {
   390  			_ = zb0007
   391  			s += msgp.StringPrefixSize + len(zb0006) + msgp.ArrayHeaderSize
   392  			for zb0008 := range zb0007 {
   393  				s += msgp.StringPrefixSize + len(zb0007[zb0008])
   394  			}
   395  		}
   396  	}
   397  	return
   398  }
   399  
   400  // JSONPool is a pool for JSON objects that unmarshal into T.
   401  type JSONPool[T any] struct {
   402  	pool    sync.Pool
   403  	emptySz int
   404  }
   405  
   406  // NewJSONPool returns a new JSONPool.
   407  func NewJSONPool[T any]() *JSONPool[T] {
   408  	var t T
   409  	sz := 128
   410  	if b, err := json.Marshal(t); err != nil {
   411  		sz = len(b)
   412  	}
   413  	return &JSONPool[T]{
   414  		pool: sync.Pool{
   415  			New: func() interface{} {
   416  				var t T
   417  				return &t
   418  			},
   419  		},
   420  		emptySz: sz,
   421  	}
   422  }
   423  
   424  func (p *JSONPool[T]) new() *T {
   425  	var zero T
   426  	t := p.pool.Get().(*T)
   427  	*t = zero
   428  	return t
   429  }
   430  
   431  // JSON is a wrapper around a T object that can be serialized.
   432  // There is an internal value
   433  type JSON[T any] struct {
   434  	p   *JSONPool[T]
   435  	val *T
   436  }
   437  
   438  // NewJSON returns a new JSONPool.
   439  // No initial value is set.
   440  func (p *JSONPool[T]) NewJSON() *JSON[T] {
   441  	var j JSON[T]
   442  	j.p = p
   443  	return &j
   444  }
   445  
   446  // NewJSONWith returns a new JSON with the provided value.
   447  func (p *JSONPool[T]) NewJSONWith(val *T) *JSON[T] {
   448  	var j JSON[T]
   449  	j.p = p
   450  	j.val = val
   451  	return &j
   452  }
   453  
   454  // Value returns the underlying value.
   455  // If not set yet, a new value is created.
   456  func (j *JSON[T]) Value() *T {
   457  	if j.val == nil {
   458  		j.val = j.p.new()
   459  	}
   460  	return j.val
   461  }
   462  
   463  // ValueOrZero returns the underlying value.
   464  // If the underlying value is nil, a zero value is returned.
   465  func (j *JSON[T]) ValueOrZero() T {
   466  	if j == nil || j.val == nil {
   467  		var t T
   468  		return t
   469  	}
   470  	return *j.val
   471  }
   472  
   473  // Set the underlying value.
   474  func (j *JSON[T]) Set(v *T) {
   475  	j.val = v
   476  }
   477  
   478  // Recycle the underlying value.
   479  func (j *JSON[T]) Recycle() {
   480  	if j.val != nil {
   481  		j.p.pool.Put(j.val)
   482  		j.val = nil
   483  	}
   484  }
   485  
   486  // MarshalMsg implements msgp.Marshaler
   487  func (j *JSON[T]) MarshalMsg(b []byte) (o []byte, err error) {
   488  	if j.val == nil {
   489  		return msgp.AppendNil(b), nil
   490  	}
   491  	buf := bytes.NewBuffer(GetByteBuffer()[:0])
   492  	defer func() {
   493  		PutByteBuffer(buf.Bytes())
   494  	}()
   495  	enc := json.NewEncoder(buf)
   496  	err = enc.Encode(j.val)
   497  	if err != nil {
   498  		return b, err
   499  	}
   500  	return msgp.AppendBytes(b, buf.Bytes()), nil
   501  }
   502  
   503  // UnmarshalMsg will JSON marshal the value and wrap as a msgp byte array.
   504  // Nil values are supported.
   505  func (j *JSON[T]) UnmarshalMsg(bytes []byte) ([]byte, error) {
   506  	if bytes, err := msgp.ReadNilBytes(bytes); err == nil {
   507  		if j.val != nil {
   508  			j.p.pool.Put(j.val)
   509  		}
   510  		j.val = nil
   511  		return bytes, nil
   512  	}
   513  	val, bytes, err := msgp.ReadBytesZC(bytes)
   514  	if err != nil {
   515  		return bytes, err
   516  	}
   517  	if j.val == nil {
   518  		j.val = j.p.new()
   519  	} else {
   520  		var t T
   521  		*j.val = t
   522  	}
   523  	return bytes, json.Unmarshal(val, j.val)
   524  }
   525  
   526  // Msgsize returns the size of an empty JSON object.
   527  func (j *JSON[T]) Msgsize() int {
   528  	return j.p.emptySz
   529  }
   530  
   531  // NoPayload is a type that can be used for handlers that do not use a payload.
   532  type NoPayload struct{}
   533  
   534  // Msgsize returns 0.
   535  func (p NoPayload) Msgsize() int {
   536  	return 0
   537  }
   538  
   539  // UnmarshalMsg satisfies the interface, but is a no-op.
   540  func (NoPayload) UnmarshalMsg(bytes []byte) ([]byte, error) {
   541  	return bytes, nil
   542  }
   543  
   544  // MarshalMsg satisfies the interface, but is a no-op.
   545  func (NoPayload) MarshalMsg(bytes []byte) ([]byte, error) {
   546  	return bytes, nil
   547  }
   548  
   549  // NewNoPayload returns an empty NoPayload struct.
   550  func NewNoPayload() NoPayload {
   551  	return NoPayload{}
   552  }
   553  
   554  // Recycle is a no-op.
   555  func (NoPayload) Recycle() {}
   556  
   557  // ArrayOf wraps an array of Messagepack compatible objects.
   558  type ArrayOf[T RoundTripper] struct {
   559  	aPool sync.Pool // Arrays
   560  	ePool sync.Pool // Elements
   561  }
   562  
   563  // NewArrayOf returns a new ArrayOf.
   564  // You must provide a function that returns a new instance of T.
   565  func NewArrayOf[T RoundTripper](newFn func() T) *ArrayOf[T] {
   566  	return &ArrayOf[T]{
   567  		ePool: sync.Pool{New: func() any {
   568  			return newFn()
   569  		}},
   570  	}
   571  }
   572  
   573  // New returns a new empty Array.
   574  func (p *ArrayOf[T]) New() *Array[T] {
   575  	return &Array[T]{
   576  		p: p,
   577  	}
   578  }
   579  
   580  // NewWith returns a new Array with the provided value (not copied).
   581  func (p *ArrayOf[T]) NewWith(val []T) *Array[T] {
   582  	return &Array[T]{
   583  		p:   p,
   584  		val: val,
   585  	}
   586  }
   587  
   588  func (p *ArrayOf[T]) newA(sz uint32) []T {
   589  	t, ok := p.aPool.Get().(*[]T)
   590  	if !ok || t == nil {
   591  		return make([]T, 0, sz)
   592  	}
   593  	t2 := *t
   594  	return t2[:0]
   595  }
   596  
   597  func (p *ArrayOf[T]) putA(v []T) {
   598  	var zero T // nil
   599  	for i, t := range v {
   600  		p.ePool.Put(t)
   601  		v[i] = zero
   602  	}
   603  	if v != nil {
   604  		v = v[:0]
   605  		p.aPool.Put(&v)
   606  	}
   607  }
   608  
   609  func (p *ArrayOf[T]) newE() T {
   610  	return p.ePool.Get().(T)
   611  }
   612  
   613  // Array provides a wrapper for an underlying array of serializable objects.
   614  type Array[T RoundTripper] struct {
   615  	p   *ArrayOf[T]
   616  	val []T
   617  }
   618  
   619  // Msgsize returns the size of the array in bytes.
   620  func (j *Array[T]) Msgsize() int {
   621  	if j.val == nil {
   622  		return msgp.NilSize
   623  	}
   624  	sz := msgp.ArrayHeaderSize
   625  	for _, v := range j.val {
   626  		sz += v.Msgsize()
   627  	}
   628  	return sz
   629  }
   630  
   631  // Value returns the underlying value.
   632  // Regular append mechanics should be observed.
   633  // If no value has been set yet, a new array is created.
   634  func (j *Array[T]) Value() []T {
   635  	if j.val == nil {
   636  		j.val = j.p.newA(10)
   637  	}
   638  	return j.val
   639  }
   640  
   641  // Append a value to the underlying array.
   642  // The returned Array is always the same as the one called.
   643  func (j *Array[T]) Append(v ...T) *Array[T] {
   644  	if j.val == nil {
   645  		j.val = j.p.newA(uint32(len(v)))
   646  	}
   647  	j.val = append(j.val, v...)
   648  	return j
   649  }
   650  
   651  // Set the underlying value.
   652  func (j *Array[T]) Set(val []T) {
   653  	j.val = val
   654  }
   655  
   656  // Recycle the underlying value.
   657  func (j *Array[T]) Recycle() {
   658  	if j.val != nil {
   659  		j.p.putA(j.val)
   660  		j.val = nil
   661  	}
   662  }
   663  
   664  // MarshalMsg implements msgp.Marshaler
   665  func (j *Array[T]) MarshalMsg(b []byte) (o []byte, err error) {
   666  	if j.val == nil {
   667  		return msgp.AppendNil(b), nil
   668  	}
   669  	if uint64(len(j.val)) > math.MaxUint32 {
   670  		return b, errors.New("array: length of array exceeds math.MaxUint32")
   671  	}
   672  	b = msgp.AppendArrayHeader(b, uint32(len(j.val)))
   673  	for _, v := range j.val {
   674  		b, err = v.MarshalMsg(b)
   675  		if err != nil {
   676  			return b, err
   677  		}
   678  	}
   679  	return b, err
   680  }
   681  
   682  // UnmarshalMsg will JSON marshal the value and wrap as a msgp byte array.
   683  // Nil values are supported.
   684  func (j *Array[T]) UnmarshalMsg(bytes []byte) ([]byte, error) {
   685  	if bytes, err := msgp.ReadNilBytes(bytes); err == nil {
   686  		if j.val != nil {
   687  			j.p.putA(j.val)
   688  		}
   689  		j.val = nil
   690  		return bytes, nil
   691  	}
   692  	l, bytes, err := msgp.ReadArrayHeaderBytes(bytes)
   693  	if err != nil {
   694  		return bytes, err
   695  	}
   696  	if j.val == nil {
   697  		j.val = j.p.newA(l)
   698  	} else {
   699  		j.val = j.val[:0]
   700  	}
   701  	for i := uint32(0); i < l; i++ {
   702  		v := j.p.newE()
   703  		bytes, err = v.UnmarshalMsg(bytes)
   704  		if err != nil {
   705  			return bytes, err
   706  		}
   707  		j.val = append(j.val, v)
   708  	}
   709  	return bytes, nil
   710  }