github.com/m3db/m3@v1.5.0/src/x/checked/bytes.go (about)

     1  // Copyright (c) 2016 Uber Technologies, Inc.
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining a copy
     4  // of this software and associated documentation files (the "Software"), to deal
     5  // in the Software without restriction, including without limitation the rights
     6  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7  // copies of the Software, and to permit persons to whom the Software is
     8  // furnished to do so, subject to the following conditions:
     9  //
    10  // The above copyright notice and this permission notice shall be included in
    11  // all copies or substantial portions of the Software.
    12  //
    13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    18  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    19  // THE SOFTWARE.
    20  
    21  package checked
    22  
    23  var (
    24  	defaultBytesOptions = NewBytesOptions()
    25  )
    26  
    27  // Bytes is a checked byte slice.
    28  type Bytes interface {
    29  	ReadWriteRef
    30  
    31  	// Bytes returns an unchecked reference to the underlying bytes, callers
    32  	// should discard the reference immediately after use and the use of
    33  	// the reference must not extend past the lifetime of the checked bytes
    34  	// itself.
    35  	Bytes() []byte
    36  
    37  	// Cap returns capacity of the bytes.
    38  	Cap() int
    39  
    40  	// Len returns the length of the bytes.
    41  	Len() int
    42  
    43  	// Resize will resize the bytes slice, this allows for reuse of the already
    44  	// allocated bytes slices.
    45  	Resize(size int)
    46  
    47  	// Append will append a single byte to the bytes slice.
    48  	Append(value byte)
    49  
    50  	// AppendAll will append bytes to the bytes slice.
    51  	AppendAll(values []byte)
    52  
    53  	// Reset will reset the reference referred to by the bytes.
    54  	Reset(v []byte)
    55  }
    56  
    57  type bytesRef struct {
    58  	RefCount
    59  
    60  	opts  BytesOptions
    61  	value []byte
    62  }
    63  
    64  // NewBytes returns a new checked byte slice.
    65  func NewBytes(value []byte, opts BytesOptions) Bytes {
    66  	if opts == nil {
    67  		opts = defaultBytesOptions
    68  	}
    69  	b := &bytesRef{
    70  		opts:  opts,
    71  		value: value,
    72  	}
    73  	b.SetOnFinalize(b)
    74  	// NB(r): Tracking objects causes interface allocation
    75  	// so avoid if we are not performing any leak detection.
    76  	if leakDetectionEnabled() {
    77  		b.TrackObject(b.value)
    78  	}
    79  	return b
    80  }
    81  
    82  func (b *bytesRef) Bytes() []byte {
    83  	b.IncReads()
    84  	v := b.value
    85  	b.DecReads()
    86  	return v
    87  }
    88  
    89  func (b *bytesRef) Cap() int {
    90  	b.IncReads()
    91  	v := cap(b.value)
    92  	b.DecReads()
    93  	return v
    94  }
    95  
    96  func (b *bytesRef) Len() int {
    97  	b.IncReads()
    98  	v := len(b.value)
    99  	b.DecReads()
   100  	return v
   101  }
   102  
   103  func (b *bytesRef) Resize(size int) {
   104  	b.IncWrites()
   105  	b.value = b.value[:size]
   106  	b.DecWrites()
   107  }
   108  
   109  func (b *bytesRef) Append(value byte) {
   110  	b.IncWrites()
   111  	b.value = append(b.value, value)
   112  	b.DecWrites()
   113  }
   114  
   115  func (b *bytesRef) AppendAll(values []byte) {
   116  	b.IncWrites()
   117  	b.value = append(b.value, values...)
   118  	b.DecWrites()
   119  }
   120  
   121  func (b *bytesRef) Reset(v []byte) {
   122  	b.IncWrites()
   123  	b.value = v
   124  	b.DecWrites()
   125  }
   126  
   127  func (b *bytesRef) OnFinalize() {
   128  	if finalizer := b.opts.Finalizer(); finalizer != nil {
   129  		finalizer.FinalizeBytes(b)
   130  	}
   131  }
   132  
   133  type bytesOptions struct {
   134  	finalizer BytesFinalizer
   135  }
   136  
   137  // NewBytesOptions returns a new set of bytes options.
   138  func NewBytesOptions() BytesOptions {
   139  	return &bytesOptions{}
   140  }
   141  
   142  func (o *bytesOptions) Finalizer() BytesFinalizer {
   143  	return o.finalizer
   144  }
   145  
   146  func (o *bytesOptions) SetFinalizer(value BytesFinalizer) BytesOptions {
   147  	opts := *o
   148  	opts.finalizer = value
   149  	return &opts
   150  }