~bigbes/core-go

565df04e3bc51985b85e41868133cc31a7074941 — Drew DeVault 10 months ago 898f2e9
model: introduce ID type

Based on UUIDv7 but represented to users in a more compact base32 form,
though all of that are internal implementation details.
3 files changed, 76 insertions(+), 1 deletions(-)

M go.mod
M go.sum
A model/id.go
M go.mod => go.mod +2 -1
@@ 15,6 15,7 @@ require (
	github.com/aws/aws-sdk-go-v2 v1.37.1
	github.com/aws/aws-sdk-go-v2/credentials v1.18.2
	github.com/aws/aws-sdk-go-v2/service/s3 v1.85.1
	github.com/aws/smithy-go v1.22.5
	github.com/emersion/go-message v0.18.2
	github.com/emersion/go-pgpmail v0.2.2
	github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43


@@ 26,6 27,7 @@ require (
	github.com/google/uuid v1.6.0
	github.com/kavu/go_reuseport v1.5.0
	github.com/lib/pq v1.10.9
	github.com/oklog/ulid/v2 v2.1.1
	github.com/prometheus/client_golang v1.16.0
	github.com/stretchr/testify v1.10.0
	github.com/vaughan0/go-ini v0.0.0-20130923145212-a98ad7ee00ec


@@ 42,7 44,6 @@ require (
	github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.1 // indirect
	github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.1 // indirect
	github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.1 // indirect
	github.com/aws/smithy-go v1.22.5 // indirect
	github.com/beorn7/perks v1.0.1 // indirect
	github.com/cespare/xxhash/v2 v2.2.0 // indirect
	github.com/cloudflare/circl v1.6.0 // indirect

M go.sum => go.sum +3 -0
@@ 150,10 150,13 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/oklog/ulid/v2 v2.1.1 h1:suPZ4ARWLOJLegGFiZZ1dFAkqzhMjL3J1TzI+5wHz8s=
github.com/oklog/ulid/v2 v2.1.1/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=

A model/id.go => model/id.go +71 -0
@@ 0,0 1,71 @@
package model

import (
	"encoding/base32"
	"fmt"
	"io"

	"github.com/google/uuid"
)

// Crockford's low-ambiguity base32 alphabet
var base32Encoding = base32.
	NewEncoding("0123456789ABCDEFGHJKMNPQRSTVWXYZ").
	WithPadding(base32.NoPadding)

type ID struct {
	uuid uuid.UUID
}

// Creates a new resource ID.
func NewID() ID {
	uuid, err := uuid.NewV7()
	if err != nil {
		panic(err)
	}
	return ID {
		uuid: uuid,
	}
}

// Returns the UUID representation of this ID.
func (id *ID) UUID() uuid.UUID {
	return id.uuid
}

// Returns the string representation of this ID.
func (id *ID) String() string {
	return base32Encoding.EncodeToString(id.uuid[:])
}

func (id ID) MarshalGQL(w io.Writer) {
	w.Write([]byte(fmt.Sprintf(`"%s"`, id.String())))
}

func (id *ID) UnmarshalGQL(v interface{}) error {
	switch v := v.(type) {
	case string:
		bytes, err := base32Encoding.DecodeString(v)
		if err != nil {
			return err
		}
		id.uuid, err = uuid.FromBytes(bytes)
		if err != nil {
			return err
		}
		return nil
	default:
		return fmt.Errorf("%T is not a valid ID", v)
	}
}

// database/sql.Scanner
func (id *ID) Scan(src any) error {
	var uuid uuid.UUID
	err := uuid.Scan(src)
	if err != nil {
		return err
	}
	id.uuid = uuid
	return nil
}