package main import ( "slices" "strings" "unique" "hakurei.app/internal/pkg" "hakurei.app/internal/rosa" ) const ( declarationAscending = iota declarationDescending nameAscending nameDescending sortOrderEnd = iota - 1 ) // packageIndex refers to metadata by name and various sort orders. type packageIndex struct { sorts [sortOrderEnd + 1][rosa.PresetUnexportedStart]*metadata names map[string]*metadata } // metadata holds [rosa.Metadata] extended with additional information. type metadata struct { *rosa.Metadata // Populated via [rosa.Toolchain.Version], [rosa.Unversioned] is equivalent // to the zero value. Otherwise, the zero value is invalid. Version string `json:"version,omitempty"` // Whether the underlying [pkg.Artifact] is present in the report. HasReport bool `json:"report"` // Ident resolved from underlying [pkg.Artifact]. ident unique.Handle[pkg.ID] // Backed by [rosa.Report], access must be prepared by HandleAccess. status []byte } // populate deterministically populates packageIndex, optionally with a report. func (index *packageIndex) populate(cache *pkg.Cache, report *rosa.Report) (err error) { if report != nil { defer report.HandleAccess(&err)() } var work [rosa.PresetUnexportedStart]*metadata index.names = make(map[string]*metadata) for p := range rosa.PresetUnexportedStart { m := metadata{ Metadata: rosa.GetMetadata(p), Version: rosa.Std.Version(p), } if cache != nil && report != nil { m.ident = cache.Ident(rosa.Std.Load(p)) status, n := report.ArtifactOf(m.ident) if n >= 0 { m.HasReport = true m.status = status } } work[p] = &m index.names[m.Name] = &m } index.sorts[declarationAscending] = work index.sorts[declarationDescending] = work slices.Reverse(index.sorts[declarationDescending][:]) index.sorts[nameAscending] = work slices.SortFunc(index.sorts[nameAscending][:], func(a, b *metadata) int { return strings.Compare(a.Name, b.Name) }) index.sorts[nameDescending] = index.sorts[nameAscending] slices.Reverse(index.sorts[nameDescending][:]) return }