diff options
author | Michael Muré <batolettre@gmail.com> | 2022-08-23 15:01:36 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-08-23 15:01:36 +0200 |
commit | 5a70e8b3a2e0fe3d1a1dcd4c24bb6bf64633cb7f (patch) | |
tree | e5382a09a45098672b6d60397eac201617fdd6ec /entity/id_interleaved.go | |
parent | 81fd7a5d8b6443e65c861f00a7387c0a3c926c66 (diff) | |
parent | 6ed4b8b7a1185ad278eb2e40b32e859f828233d9 (diff) | |
download | git-bug-5a70e8b3a2e0fe3d1a1dcd4c24bb6bf64633cb7f.tar.gz |
Merge pull request #664 from MichaelMure/combined-id-rework
bug: have a type for combined ids, fix #653
Diffstat (limited to 'entity/id_interleaved.go')
-rw-r--r-- | entity/id_interleaved.go | 84 |
1 files changed, 81 insertions, 3 deletions
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 |