openmeter / subscription /specpath.go
Leon4gr45's picture
Upload folder using huggingface_hub (part 7)
16cdcb7 verified
Raw
History Blame Contribute Delete
3.68 kB
package subscription
import (
"fmt"
"strconv"
"strings"
"github.com/samber/lo"
)
type SpecPath string
const (
phasePathPrefix = "phases"
itemPathPrefix = "items"
versionPathPrefix = "idx"
)
type SpecPathType string
const (
SpecPathTypePhase SpecPathType = "phase"
SpecPathTypeItem SpecPathType = "item"
SpecPathTypeItemVersion SpecPathType = "item_version"
)
// Lets implement JSON Unmarshaler for Path
func (p *SpecPath) UnmarshalJSON(data []byte) error {
if err := SpecPath(data).Validate(); err != nil {
return fmt.Errorf("path validation failed: %s", err)
}
*p = SpecPath(data)
return nil
}
// Lets implement JSON Marshaler for Path
func (p SpecPath) MarshalJSON() ([]byte, error) {
return []byte(fmt.Sprintf(`"%s"`, p)), nil
}
func (p SpecPath) seg() []string {
// For a properly formatted path the first segment is empty
return strings.Split(string(p), "/")[1:]
}
// Checks whether p is a parent of other where parent means all segments of p are present and in order in other
func (p SpecPath) IsParentOf(other SpecPath) bool {
segments := p.seg()
otherSegments := other.seg()
if len(otherSegments) < len(segments) {
return false
}
for i, s := range segments {
if otherSegments[i] != s {
return false
}
}
return true
}
// Lets implement validation for Path
func (p SpecPath) Validate() error {
strVal := string(p)
if !strings.HasPrefix(strVal, "/") {
return &PatchValidationError{
Msg: fmt.Sprintf("invalid path: %s, should start with /", strVal),
}
}
segments := p.seg()
if len(segments) != 2 && len(segments) != 4 && len(segments) != 6 {
return &PatchValidationError{
Msg: fmt.Sprintf("invalid path: %s, should have 2, 4 or 6 segments, has %d", strVal, len(segments)),
}
}
if segments[0] != phasePathPrefix {
return &PatchValidationError{Msg: fmt.Sprintf("invalid path: %s, first segment should be %s", strVal, phasePathPrefix)}
}
if len(segments) == 4 && segments[2] != itemPathPrefix {
return &PatchValidationError{Msg: fmt.Sprintf("invalid path: %s, third segment should be %s", strVal, itemPathPrefix)}
}
if len(segments) == 6 && segments[4] != versionPathPrefix {
return &PatchValidationError{Msg: fmt.Sprintf("invalid path: %s, fifth segment should be %s", strVal, versionPathPrefix)}
}
if lo.SomeBy(segments, func(s string) bool { return s == "" }) {
return &PatchValidationError{Msg: fmt.Sprintf("invalid path: %s, segments should not be empty", strVal)}
}
return nil
}
func (p SpecPath) Type() SpecPathType {
if len(p.seg()) == 6 {
return SpecPathTypeItemVersion
}
if len(p.seg()) == 4 {
return SpecPathTypeItem
}
// As validity is not guaranteed, Phase is the placeholder type for invalid values
return SpecPathTypePhase
}
func (p SpecPath) PhaseKey() string {
return p.seg()[1]
}
func (p SpecPath) ItemKey() string {
if p.Type() != SpecPathTypeItem {
return ""
}
return p.seg()[3]
}
func (p SpecPath) ItemVersion() int {
if p.Type() != SpecPathTypeItemVersion {
return -1
}
idxStr := p.seg()[5]
idx, err := strconv.Atoi(idxStr)
if err != nil {
return -1
}
return idx
}
// TODO: add SpecPath to FieldSelector conversion method
func NewPhasePath(phaseKey string) SpecPath {
return SpecPath(fmt.Sprintf("/%s/%s", phasePathPrefix, phaseKey))
}
func NewItemPath(phaseKey, itemKey string) SpecPath {
phasePath := NewPhasePath(phaseKey)
return SpecPath(fmt.Sprintf("%s/%s/%s", phasePath, itemPathPrefix, itemKey))
}
func NewItemVersionPath(phaseKey, itemKey string, idx int) SpecPath {
itemPath := NewItemPath(phaseKey, itemKey)
return SpecPath(fmt.Sprintf("%s/%s/%d", itemPath, versionPathPrefix, idx))
}