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}
68
69/*
70 * Sorting
71 */
72
73type Alphabetical []Id
74
75func (a Alphabetical) Len() int {
76 return len(a)
77}
78
79func (a Alphabetical) Less(i, j int) bool {
80 return a[i] < a[j]
81}
82
83func (a Alphabetical) Swap(i, j int) {
84 a[i], a[j] = a[j], a[i]
85}