diff --git a/internal/types/id.go b/internal/types/id.go new file mode 100644 index 0000000..802e6c1 --- /dev/null +++ b/internal/types/id.go @@ -0,0 +1,64 @@ +package types + +import ( + "fmt" + "regexp" + "strings" +) + +var ( + idRegex = regexp.MustCompile(`(.*?)(@(.*))?:(.*)`) +) + +// ID an id of a file consists of at least a Bucket and a Key. Version is optional. +// Can also be used as an ID for a directory. When the key ends with "/" it is treated as dir. +type ID struct { + Bucket string // Name of the bucket + Key string // Key of the object + Version string // Version of the object. For now we ignore it +} + +// String Return String representation of an ID +// Looks like this: "bucketName@version:/id/of/obj" or "bucketName:/id/of/obj" +func (i *ID) String() string { + i.Normalize() + if i.Version == "" { + return fmt.Sprintf("%s:%s", i.Bucket, i.Key) + } else { + return fmt.Sprintf("%s@%s:%s", i.Bucket, i.Version, i.Key) + } +} + +// Normalize normalzes the key to have a "/" prefix +func (i *ID) Normalize() { + if !strings.HasPrefix(i.Key, "/") { + i.Key = "/" + i.Key + } +} + +// Valid checks if bucket and key is not empty +func (i *ID) Valid() bool { + return i.Bucket != "" && i.Key != "" +} + +// ParseID parses a string to an ID. Null if invalid +func ParseID(id string) *ID { + match := idRegex.FindStringSubmatch(id) + if match == nil { + return nil + } + + rtn := &ID{ + Bucket: match[1], + Version: match[3], + Key: match[4], + } + + if !rtn.Valid() { + return nil + } + + rtn.Normalize() + + return rtn +}