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 }