package bucket import ( "errors" "fmt" "net/url" "strings" ) type Photo string const photoPrefix = "photo/" const photoMetadataPrefix = "photometadata/" var ErrorInvalidPhoto = errors.New("invalid photo") func (p Photo) Validate() error { if !strings.HasPrefix(string(p), photoPrefix) { return fmt.Errorf("%w: %v", ErrorInvalidPhoto, p) } if strings.HasSuffix(string(p), "/") { return fmt.Errorf("%w: %v", ErrorInvalidPhoto, p) } return nil } func (p Photo) String() string { return string(p) } func (p Photo) Path() *url.URL { return &url.URL{ Path: string(p), } } type PhotoMetadata string func (p Photo) Metadata(name string) PhotoMetadata { objectBase := strings.Replace(string(p), photoPrefix, photoMetadataPrefix, 1) return PhotoMetadata(objectBase + "/" + name) } func (m PhotoMetadata) String() string { return string(m) } func (m PhotoMetadata) Path() *url.URL { return &url.URL{ Path: string(m), } } func (p Photo) MetadataSize() PhotoMetadata { return p.Metadata("size") } func (p Photo) MetadataDate() PhotoMetadata { return p.Metadata("date") } func (p Photo) MetadataTitle() PhotoMetadata { return p.Metadata("title") } func (p Photo) MetadataTags() PhotoMetadata { return p.Metadata("tags") }