github.com/status-im/status-go@v1.1.0/sqlite/fields.go (about) 1 package sqlite 2 3 import ( 4 "database/sql/driver" 5 "encoding/json" 6 "errors" 7 "fmt" 8 "math" 9 "math/big" 10 "reflect" 11 ) 12 13 // JSONBlob type for marshaling/unmarshaling inner type to json. 14 type JSONBlob struct { 15 Data interface{} 16 Valid bool 17 } 18 19 // Scan implements interface. 20 func (blob *JSONBlob) Scan(value interface{}) error { 21 dataVal := reflect.ValueOf(blob.Data) 22 blob.Valid = false 23 if value == nil || dataVal.Kind() == reflect.Ptr && dataVal.IsNil() { 24 return nil 25 } 26 27 var bytes []byte 28 ok := true 29 switch v := value.(type) { 30 case []byte: 31 bytes, ok = value.([]byte) 32 case string: 33 bytes = []byte(v) 34 default: 35 ok = false 36 } 37 if !ok { 38 return errors.New("not a byte slice or string") 39 } 40 if len(bytes) == 0 { 41 return nil 42 } 43 err := json.Unmarshal(bytes, blob.Data) 44 blob.Valid = err == nil 45 return err 46 } 47 48 // Value implements interface. 49 func (blob *JSONBlob) Value() (driver.Value, error) { 50 dataVal := reflect.ValueOf(blob.Data) 51 if (blob.Data == nil) || (dataVal.Kind() == reflect.Ptr && dataVal.IsNil()) { 52 return nil, nil 53 } 54 55 switch dataVal.Kind() { 56 case reflect.Slice, reflect.Array, reflect.Map: 57 if dataVal.Len() == 0 { 58 return nil, nil 59 } 60 } 61 62 return json.Marshal(blob.Data) 63 } 64 65 func BigIntToClampedInt64(val *big.Int) *int64 { 66 if val == nil { 67 return nil 68 } 69 var v int64 70 if val.IsInt64() { 71 v = val.Int64() 72 } else { 73 v = math.MaxInt64 74 } 75 return &v 76 } 77 78 // BigIntToPadded128BitsStr converts a big.Int to a string, padding it with 0 to account for 128 bits size 79 // Returns nil if input val is nil 80 // This should work to sort and compare big.Ints values in SQLite 81 func BigIntToPadded128BitsStr(val *big.Int) *string { 82 if val == nil { 83 return nil 84 } 85 hexStr := val.Text(16) 86 res := new(string) 87 *res = fmt.Sprintf("%032s", hexStr) 88 return res 89 } 90 91 func Int64ToPadded128BitsStr(val int64) *string { 92 res := fmt.Sprintf("%032x", val) 93 return &res 94 }