status-im/status-go

View on GitHub
sqlite/fields.go

Summary

Maintainability
A
0 mins
Test Coverage
B
82%
package sqlite

import (
    "database/sql/driver"
    "encoding/json"
    "errors"
    "fmt"
    "math"
    "math/big"
    "reflect"
)

// JSONBlob type for marshaling/unmarshaling inner type to json.
type JSONBlob struct {
    Data  interface{}
    Valid bool
}

// Scan implements interface.
func (blob *JSONBlob) Scan(value interface{}) error {
    dataVal := reflect.ValueOf(blob.Data)
    blob.Valid = false
    if value == nil || dataVal.Kind() == reflect.Ptr && dataVal.IsNil() {
        return nil
    }

    var bytes []byte
    ok := true
    switch v := value.(type) {
    case []byte:
        bytes, ok = value.([]byte)
    case string:
        bytes = []byte(v)
    default:
        ok = false
    }
    if !ok {
        return errors.New("not a byte slice or string")
    }
    if len(bytes) == 0 {
        return nil
    }
    err := json.Unmarshal(bytes, blob.Data)
    blob.Valid = err == nil
    return err
}

// Value implements interface.
func (blob *JSONBlob) Value() (driver.Value, error) {
    dataVal := reflect.ValueOf(blob.Data)
    if (blob.Data == nil) || (dataVal.Kind() == reflect.Ptr && dataVal.IsNil()) {
        return nil, nil
    }

    switch dataVal.Kind() {
    case reflect.Slice, reflect.Array, reflect.Map:
        if dataVal.Len() == 0 {
            return nil, nil
        }
    }

    return json.Marshal(blob.Data)
}

func BigIntToClampedInt64(val *big.Int) *int64 {
    if val == nil {
        return nil
    }
    var v int64
    if val.IsInt64() {
        v = val.Int64()
    } else {
        v = math.MaxInt64
    }
    return &v
}

// BigIntToPadded128BitsStr converts a big.Int to a string, padding it with 0 to account for 128 bits size
// Returns nil if input val is nil
// This should work to sort and compare big.Ints values in SQLite
func BigIntToPadded128BitsStr(val *big.Int) *string {
    if val == nil {
        return nil
    }
    hexStr := val.Text(16)
    res := new(string)
    *res = fmt.Sprintf("%032s", hexStr)
    return res
}

func Int64ToPadded128BitsStr(val int64) *string {
    res := fmt.Sprintf("%032x", val)
    return &res
}