x/model: prefix NamePart constants with Part

This commit is contained in:
Blake Mizerany 2024-04-07 15:17:02 -07:00
parent ff68227ca1
commit 4eb7acf84b
2 changed files with 68 additions and 68 deletions

View File

@ -33,30 +33,30 @@ type NamePart int
// Levels of concreteness // Levels of concreteness
const ( const (
Host NamePart = iota PartHost NamePart = iota
Namespace PartNamespace
Model PartModel
Tag PartTag
Build PartBuild
Digest PartDigest
// Invalid is a special part that is used to indicate that a part is // Invalid is a special part that is used to indicate that a part is
// invalid. It is not a valid part of a Name. // invalid. It is not a valid part of a Name.
// //
// It should be kept as the last part in the list. // It should be kept as the last part in the list.
Invalid PartInvalid
NumParts = Invalid NumParts = PartInvalid
) )
var kindNames = map[NamePart]string{ var kindNames = map[NamePart]string{
Invalid: "Invalid", PartInvalid: "Invalid",
Host: "Host", PartHost: "Host",
Namespace: "Namespace", PartNamespace: "Namespace",
Model: "Name", PartModel: "Name",
Tag: "Tag", PartTag: "Tag",
Build: "Build", PartBuild: "Build",
Digest: "Digest", PartDigest: "Digest",
} }
func (k NamePart) String() string { func (k NamePart) String() string {
@ -139,7 +139,7 @@ type Name struct {
func ParseName(s string) Name { func ParseName(s string) Name {
var r Name var r Name
for kind, part := range Parts(s) { for kind, part := range Parts(s) {
if kind == Invalid { if kind == PartInvalid {
return Name{} return Name{}
} }
r.parts[kind] = part r.parts[kind] = part
@ -163,7 +163,7 @@ func Fill(dst, src Name) Name {
// WithBuild returns a copy of r with the build set to the given string. // WithBuild returns a copy of r with the build set to the given string.
func (r Name) WithBuild(build string) Name { func (r Name) WithBuild(build string) Name {
r.parts[Build] = build r.parts[PartBuild] = build
return r return r
} }
@ -196,7 +196,7 @@ func (r Name) slice(from, to NamePart) Name {
// DisplayModel returns the a display string composed of the model only. // DisplayModel returns the a display string composed of the model only.
func (r Name) DisplayModel() string { func (r Name) DisplayModel() string {
return r.parts[Model] return r.parts[PartModel]
} }
// DisplayFullest returns the fullest possible display string in form: // DisplayFullest returns the fullest possible display string in form:
@ -208,7 +208,7 @@ func (r Name) DisplayModel() string {
// It does not include the build part. For the fullest possible display // It does not include the build part. For the fullest possible display
// string with the build, use [Name.String]. // string with the build, use [Name.String].
func (r Name) DisplayFullest() string { func (r Name) DisplayFullest() string {
return r.slice(Host, Tag).String() return r.slice(PartHost, PartTag).String()
} }
// DisplayShort returns the fullest possible display string in form: // DisplayShort returns the fullest possible display string in form:
@ -217,7 +217,7 @@ func (r Name) DisplayFullest() string {
// //
// If any part is missing, it is omitted from the display string. // If any part is missing, it is omitted from the display string.
func (r Name) DisplayShort() string { func (r Name) DisplayShort() string {
return r.slice(Model, Tag).String() return r.slice(PartModel, PartTag).String()
} }
// DisplayLong returns the fullest possible display string in form: // DisplayLong returns the fullest possible display string in form:
@ -226,16 +226,16 @@ func (r Name) DisplayShort() string {
// //
// If any part is missing, it is omitted from the display string. // If any part is missing, it is omitted from the display string.
func (r Name) DisplayLong() string { func (r Name) DisplayLong() string {
return r.slice(Namespace, Tag).String() return r.slice(PartNamespace, PartTag).String()
} }
var seps = [...]string{ var seps = [...]string{
Host: "/", PartHost: "/",
Namespace: "/", PartNamespace: "/",
Model: ":", PartModel: ":",
Tag: "+", PartTag: "+",
Build: "@", PartBuild: "@",
Digest: "", PartDigest: "",
} }
// WriteTo implements io.WriterTo. It writes the fullest possible display // WriteTo implements io.WriterTo. It writes the fullest possible display
@ -253,7 +253,7 @@ func (r Name) WriteTo(w io.Writer) (n int64, err error) {
if r.parts[i] == "" { if r.parts[i] == "" {
continue continue
} }
if n > 0 || NamePart(i) == Digest { if n > 0 || NamePart(i) == PartDigest {
n1, err := io.WriteString(w, seps[i-1]) n1, err := io.WriteString(w, seps[i-1])
n += int64(n1) n += int64(n1)
if err != nil { if err != nil {
@ -380,13 +380,13 @@ func (r Name) Value() (driver.Value, error) {
// Complete reports whether the Name is fully qualified. That is it has a // Complete reports whether the Name is fully qualified. That is it has a
// domain, namespace, name, tag, and build. // domain, namespace, name, tag, and build.
func (r Name) Complete() bool { func (r Name) Complete() bool {
return !slices.Contains(r.parts[:Digest], "") return !slices.Contains(r.parts[:PartDigest], "")
} }
// CompleteNoBuild is like [Name.Complete] but it does not require the // CompleteNoBuild is like [Name.Complete] but it does not require the
// build part to be present. // build part to be present.
func (r Name) CompleteNoBuild() bool { func (r Name) CompleteNoBuild() bool {
return !slices.Contains(r.parts[:Build], "") return !slices.Contains(r.parts[:PartBuild], "")
} }
// Resolved reports true if the Name has a valid digest. // Resolved reports true if the Name has a valid digest.
@ -394,7 +394,7 @@ func (r Name) CompleteNoBuild() bool {
// It is possible to have a valid Name, or a complete Name that is not // It is possible to have a valid Name, or a complete Name that is not
// resolved. // resolved.
func (r Name) Resolved() bool { func (r Name) Resolved() bool {
return r.parts[Digest] != "" return r.parts[PartDigest] != ""
} }
// Digest returns the digest part of the Name, if any. // Digest returns the digest part of the Name, if any.
@ -402,7 +402,7 @@ func (r Name) Resolved() bool {
// If Digest returns a non-empty string, then [Name.Resolved] will return // If Digest returns a non-empty string, then [Name.Resolved] will return
// true, and digest is considered valid. // true, and digest is considered valid.
func (r Name) Digest() string { func (r Name) Digest() string {
return r.parts[Digest] return r.parts[PartDigest]
} }
// EqualFold reports whether r and o are equivalent model names, ignoring // EqualFold reports whether r and o are equivalent model names, ignoring
@ -462,27 +462,27 @@ func Parts(s string) iter.Seq2[NamePart, string] {
yieldValid := func(kind NamePart, part string) bool { yieldValid := func(kind NamePart, part string) bool {
if !isValidPart(kind, part) { if !isValidPart(kind, part) {
yield(Invalid, "") yield(PartInvalid, "")
return false return false
} }
return yield(kind, part) return yield(kind, part)
} }
partLen := 0 partLen := 0
state, j := Digest, len(s) state, j := PartDigest, len(s)
for i := len(s) - 1; i >= 0; i-- { for i := len(s) - 1; i >= 0; i-- {
if partLen++; partLen > MaxNamePartLen { if partLen++; partLen > MaxNamePartLen {
yield(Invalid, "") yield(PartInvalid, "")
return return
} }
switch s[i] { switch s[i] {
case '@': case '@':
switch state { switch state {
case Digest: case PartDigest:
part := s[i+1:] part := s[i+1:]
if isValidDigest(part) { if isValidDigest(part) {
if !yield(Digest, part) { if !yield(PartDigest, part) {
return return
} }
if i == 0 { if i == 0 {
@ -497,77 +497,77 @@ func Parts(s string) iter.Seq2[NamePart, string] {
return return
} }
} else { } else {
yield(Invalid, "") yield(PartInvalid, "")
return return
} }
state, j, partLen = Build, i, 0 state, j, partLen = PartBuild, i, 0
default: default:
yield(Invalid, "") yield(PartInvalid, "")
return return
} }
case '+': case '+':
switch state { switch state {
case Build, Digest: case PartBuild, PartDigest:
if !yieldValid(Build, s[i+1:j]) { if !yieldValid(PartBuild, s[i+1:j]) {
return return
} }
state, j, partLen = Tag, i, 0 state, j, partLen = PartTag, i, 0
default: default:
yield(Invalid, "") yield(PartInvalid, "")
return return
} }
case ':': case ':':
switch state { switch state {
case Tag, Build, Digest: case PartTag, PartBuild, PartDigest:
if !yieldValid(Tag, s[i+1:j]) { if !yieldValid(PartTag, s[i+1:j]) {
return return
} }
state, j, partLen = Model, i, 0 state, j, partLen = PartModel, i, 0
default: default:
yield(Invalid, "") yield(PartInvalid, "")
return return
} }
case '/': case '/':
switch state { switch state {
case Model, Tag, Build, Digest: case PartModel, PartTag, PartBuild, PartDigest:
if !yieldValid(Model, s[i+1:j]) { if !yieldValid(PartModel, s[i+1:j]) {
return return
} }
state, j = Namespace, i state, j = PartNamespace, i
case Namespace: case PartNamespace:
if !yieldValid(Namespace, s[i+1:j]) { if !yieldValid(PartNamespace, s[i+1:j]) {
return return
} }
state, j, partLen = Host, i, 0 state, j, partLen = PartHost, i, 0
default: default:
yield(Invalid, "") yield(PartInvalid, "")
return return
} }
default: default:
if !isValidByte(state, s[i]) { if !isValidByte(state, s[i]) {
yield(Invalid, "") yield(PartInvalid, "")
return return
} }
} }
} }
if state <= Namespace { if state <= PartNamespace {
yieldValid(state, s[:j]) yieldValid(state, s[:j])
} else { } else {
yieldValid(Model, s[:j]) yieldValid(PartModel, s[:j])
} }
} }
} }
// Valid returns true if the Name has a valid nick. To know if a Name is // Valid returns true if the Name hPartas a valid nick. To know if a Name is
// "complete", use [Name.Complete]. // "complete", use [Name.Complete].
func (r Name) Valid() bool { func (r Name) Valid() bool {
// Parts ensures we only have valid parts, so no need to validate // Parts ensures we only have valid parts, so no need to validate
// them here, only check if we have a name or not. // them here, only check if we have a name or not.
return r.parts[Model] != "" return r.parts[PartModel] != ""
} }
// isValidPart returns true if given part is valid ascii [a-zA-Z0-9_\.-] // isValidPart returns Parttrue if given part is valid ascii [a-zA-Z0-9_\.-]
func isValidPart(kind NamePart, s string) bool { func isValidPart(kind NamePart, s string) bool {
if s == "" { if s == "" {
return false return false
@ -581,7 +581,7 @@ func isValidPart(kind NamePart, s string) bool {
} }
func isValidByte(kind NamePart, c byte) bool { func isValidByte(kind NamePart, c byte) bool {
if kind == Namespace && c == '.' { if kind == PartNamespace && c == '.' {
return false return false
} }
if c == '.' || c == '-' { if c == '.' || c == '-' {

View File

@ -18,12 +18,12 @@ type fields struct {
func fieldsFromName(p Name) fields { func fieldsFromName(p Name) fields {
return fields{ return fields{
host: p.parts[Host], host: p.parts[PartHost],
namespace: p.parts[Namespace], namespace: p.parts[PartNamespace],
model: p.parts[Model], model: p.parts[PartModel],
tag: p.parts[Tag], tag: p.parts[PartTag],
build: p.parts[Build], build: p.parts[PartBuild],
digest: p.parts[Digest], digest: p.parts[PartDigest],
} }
} }