diff options
Diffstat (limited to 'entity')
-rw-r--r-- | entity/id.go | 18 | ||||
-rw-r--r-- | entity/id_interleaved.go | 84 | ||||
-rw-r--r-- | entity/id_interleaved_test.go | 2 |
3 files changed, 82 insertions, 22 deletions
diff --git a/entity/id.go b/entity/id.go index 8f3dc25b..49398da8 100644 --- a/entity/id.go +++ b/entity/id.go @@ -79,21 +79,3 @@ func (i Id) Validate() error { } return nil } - -/* - * Sorting - */ - -type Alphabetical []Id - -func (a Alphabetical) Len() int { - return len(a) -} - -func (a Alphabetical) Less(i, j int) bool { - return a[i] < a[j] -} - -func (a Alphabetical) Swap(i, j int) { - a[i], a[j] = a[j], a[i] -} diff --git a/entity/id_interleaved.go b/entity/id_interleaved.go index 0ce2ba00..28c59a42 100644 --- a/entity/id_interleaved.go +++ b/entity/id_interleaved.go @@ -1,13 +1,91 @@ package entity import ( + "fmt" + "io" "strings" + + "github.com/pkg/errors" ) +const UnsetCombinedId = CombinedId("unset") + +// CombinedId is an Id holding information from both a primary Id and a secondary Id. +// While it looks like a regular Id, do not just cast from one to another. +// Instead, use CombineIds and SeparateIds to create it and split it. +type CombinedId string + +// String return the identifier as a string +func (ci CombinedId) String() string { + return string(ci) +} + +// Human return the identifier, shortened for human consumption +func (ci CombinedId) Human() string { + format := fmt.Sprintf("%%.%ds", humanIdLength) + return fmt.Sprintf(format, ci) +} + +func (ci CombinedId) HasPrefix(prefix string) bool { + return strings.HasPrefix(string(ci), prefix) +} + +// UnmarshalGQL implement the Unmarshaler interface for gqlgen +func (ci *CombinedId) UnmarshalGQL(v interface{}) error { + _, ok := v.(string) + if !ok { + return fmt.Errorf("CombinedIds must be strings") + } + + *ci = v.(CombinedId) + + if err := ci.Validate(); err != nil { + return errors.Wrap(err, "invalid CombinedId") + } + + return nil +} + +// MarshalGQL implement the Marshaler interface for gqlgen +func (ci CombinedId) MarshalGQL(w io.Writer) { + _, _ = w.Write([]byte(`"` + ci.String() + `"`)) +} + +// Validate tell if the Id is valid +func (ci CombinedId) Validate() error { + // Special case to detect outdated repo + if len(ci) == 40 { + return fmt.Errorf("outdated repository format, please use https://github.com/MichaelMure/git-bug-migration to upgrade") + } + if len(ci) != idLength { + return fmt.Errorf("invalid length") + } + for _, r := range ci { + if (r < 'a' || r > 'z') && (r < '0' || r > '9') { + return fmt.Errorf("invalid character") + } + } + return nil +} + +// PrimaryPrefix is a helper to extract the primary prefix. +// If practical, use SeparateIds instead. +func (ci CombinedId) PrimaryPrefix() string { + primaryPrefix, _ := SeparateIds(string(ci)) + return primaryPrefix +} + +// SecondaryPrefix is a helper to extract the secondary prefix. +// If practical, use SeparateIds instead. +func (ci CombinedId) SecondaryPrefix() string { + _, secondaryPrefix := SeparateIds(string(ci)) + return secondaryPrefix +} + // CombineIds compute a merged Id holding information from both the primary Id // and the secondary Id. // -// This allow to later find efficiently a secondary element because we can access +// This allows to later find efficiently a secondary element because we can access // the primary one directly instead of searching for a primary that has a // secondary matching the Id. // @@ -32,7 +110,7 @@ import ( // 7: 4P, 3S // 10: 6P, 4S // 16: 11P, 5S -func CombineIds(primary Id, secondary Id) Id { +func CombineIds(primary Id, secondary Id) CombinedId { var id strings.Builder for i := 0; i < idLength; i++ { @@ -46,7 +124,7 @@ func CombineIds(primary Id, secondary Id) Id { } } - return Id(id.String()) + return CombinedId(id.String()) } // SeparateIds extract primary and secondary prefix from an arbitrary length prefix diff --git a/entity/id_interleaved_test.go b/entity/id_interleaved_test.go index ef9218c9..1dc79145 100644 --- a/entity/id_interleaved_test.go +++ b/entity/id_interleaved_test.go @@ -9,7 +9,7 @@ import ( func TestInterleaved(t *testing.T) { primary := Id("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWX______________") secondary := Id("YZ0123456789+/________________________________________________") - expectedId := Id("aYbZc0def1ghij2klmn3opqr4stuv5wxyz6ABCD7EFGH8IJKL9MNOP+QRST/UVWX") + expectedId := CombinedId("aYbZc0def1ghij2klmn3opqr4stuv5wxyz6ABCD7EFGH8IJKL9MNOP+QRST/UVWX") interleaved := CombineIds(primary, secondary) require.Equal(t, expectedId, interleaved) |