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 }