Skip to content

Commit

Permalink
shared/dbutil: spannerutil.Int utility function
Browse files Browse the repository at this point in the history
This will make it simpler to pass output locations to our Spanner
library, which apparently only likes int64 out of all Go's integer
types.

In general, it is preferable to add EncodeSpanner/DecodeSpanner meethods
to our specialized int types, but this can be used for types we don't
own or otherwise can't put methods on (in particular, int32).

Change-Id: Ibdb64e4483e1de32fa13f2f4b464887fadd6e48c
  • Loading branch information
thepaul authored and Storj Robot committed May 5, 2024
1 parent 73c658f commit 3b6cce9
Showing 1 changed file with 46 additions and 0 deletions.
46 changes: 46 additions & 0 deletions shared/dbutil/spannerutil/encoding.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright (C) 2024 Storj Labs, Inc.
// See LICENSE for copying information.

package spannerutil

import (
"strconv"

"github.com/zeebo/errs"
)

// inty requires that a type has some form of signed or unsigned integer as an underlying type.
type inty interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64
}

// IntValueDecoder is a type wrapping an int pointer so it can decode integer values from
// Spanner directly (Spanner prefers to work only in int64s).
type IntValueDecoder[T inty] struct {
pointer *T
}

// DecodeSpanner decodes a value from a Spanner-stored type to the appropriate int type.
// It implements spanner.Decoder.
func (s IntValueDecoder[T]) DecodeSpanner(input any) error {
if sVal, ok := input.(string); ok {
iVal, err := strconv.ParseInt(sVal, 10, 64)
if err != nil {
return err
}
if int64(T(iVal)) != iVal {
return errs.New("value out of bounds for %T: %d", T(0), iVal)
}
*s.pointer = T(iVal)
return nil
}
return errs.New("unable to decode %T to %T", input, T(0))
}

// Int wraps a pointer to an int-based type in a type that can be decoded directly from Spanner.
//
// In general, it is preferable to add EncodeSpanner/DecodeSpanner methods to our specialized
// int types, but this can be used for types we don't own or otherwise can't put methods on.
func Int[T inty](val *T) IntValueDecoder[T] {
return IntValueDecoder[T]{pointer: val}
}

0 comments on commit 3b6cce9

Please sign in to comment.