id.go

 1package entity
 2
 3import (
 4	"fmt"
 5	"io"
 6	"strings"
 7
 8	"github.com/pkg/errors"
 9)
10
11const IdLengthSHA1 = 40
12const IdLengthSHA256 = 64
13const humanIdLength = 7
14
15const UnsetId = Id("unset")
16
17// Id is an identifier for an entity or part of an entity
18type Id string
19
20// String return the identifier as a string
21func (i Id) String() string {
22	return string(i)
23}
24
25// Human return the identifier, shortened for human consumption
26func (i Id) Human() string {
27	format := fmt.Sprintf("%%.%ds", humanIdLength)
28	return fmt.Sprintf(format, i)
29}
30
31func (i Id) HasPrefix(prefix string) bool {
32	return strings.HasPrefix(string(i), prefix)
33}
34
35// UnmarshalGQL implement the Unmarshaler interface for gqlgen
36func (i *Id) UnmarshalGQL(v interface{}) error {
37	_, ok := v.(string)
38	if !ok {
39		return fmt.Errorf("IDs must be strings")
40	}
41
42	*i = v.(Id)
43
44	if err := i.Validate(); err != nil {
45		return errors.Wrap(err, "invalid ID")
46	}
47
48	return nil
49}
50
51// MarshalGQL implement the Marshaler interface for gqlgen
52func (i Id) MarshalGQL(w io.Writer) {
53	_, _ = w.Write([]byte(`"` + i.String() + `"`))
54}
55
56// IsValid tell if the Id is valid
57func (i Id) Validate() error {
58	if len(i) != IdLengthSHA1 && len(i) != IdLengthSHA256 {
59		return fmt.Errorf("invalid length")
60	}
61	for _, r := range i {
62		if (r < 'a' || r > 'z') && (r < '0' || r > '9') {
63			return fmt.Errorf("invalid character")
64		}
65	}
66	return nil
67}