github.com/gogf/gf/v2@v2.7.4/container/gtype/gtype_bytes.go (about) 1 // Copyright GoFrame Author(https://goframe.org). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/gogf/gf. 6 7 package gtype 8 9 import ( 10 "bytes" 11 "encoding/base64" 12 "sync/atomic" 13 14 "github.com/gogf/gf/v2/errors/gerror" 15 "github.com/gogf/gf/v2/util/gconv" 16 ) 17 18 // Bytes is a struct for concurrent-safe operation for type []byte. 19 type Bytes struct { 20 value atomic.Value 21 } 22 23 // NewBytes creates and returns a concurrent-safe object for []byte type, 24 // with given initial value `value`. 25 func NewBytes(value ...[]byte) *Bytes { 26 t := &Bytes{} 27 if len(value) > 0 { 28 t.value.Store(value[0]) 29 } 30 return t 31 } 32 33 // Clone clones and returns a new shallow copy object for []byte type. 34 func (v *Bytes) Clone() *Bytes { 35 return NewBytes(v.Val()) 36 } 37 38 // Set atomically stores `value` into t.value and returns the previous value of t.value. 39 // Note: The parameter `value` cannot be nil. 40 func (v *Bytes) Set(value []byte) (old []byte) { 41 old = v.Val() 42 v.value.Store(value) 43 return 44 } 45 46 // Val atomically loads and returns t.value. 47 func (v *Bytes) Val() []byte { 48 if s := v.value.Load(); s != nil { 49 return s.([]byte) 50 } 51 return nil 52 } 53 54 // String implements String interface for string printing. 55 func (v *Bytes) String() string { 56 return string(v.Val()) 57 } 58 59 // MarshalJSON implements the interface MarshalJSON for json.Marshal. 60 func (v Bytes) MarshalJSON() ([]byte, error) { 61 val := v.Val() 62 dst := make([]byte, base64.StdEncoding.EncodedLen(len(val))) 63 base64.StdEncoding.Encode(dst, val) 64 return []byte(`"` + string(dst) + `"`), nil 65 } 66 67 // UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal. 68 func (v *Bytes) UnmarshalJSON(b []byte) error { 69 var ( 70 src = make([]byte, base64.StdEncoding.DecodedLen(len(b))) 71 n, err = base64.StdEncoding.Decode(src, bytes.Trim(b, `"`)) 72 ) 73 if err != nil { 74 err = gerror.Wrap(err, `base64.StdEncoding.Decode failed`) 75 return err 76 } 77 v.Set(src[:n]) 78 return nil 79 } 80 81 // UnmarshalValue is an interface implement which sets any type of value for `v`. 82 func (v *Bytes) UnmarshalValue(value interface{}) error { 83 v.Set(gconv.Bytes(value)) 84 return nil 85 } 86 87 // DeepCopy implements interface for deep copy of current type. 88 func (v *Bytes) DeepCopy() interface{} { 89 if v == nil { 90 return nil 91 } 92 oldBytes := v.Val() 93 newBytes := make([]byte, len(oldBytes)) 94 copy(newBytes, oldBytes) 95 return NewBytes(newBytes) 96 }