aboutsummaryrefslogtreecommitdiffhomepage
path: root/container
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2026-01-11 04:16:00 +0900
committerOphestra <cat@gensokyo.uk>2026-01-11 04:18:11 +0900
commitec9343ebd625cc97a0dd8b09f030f84b142b7ca4 (patch)
treed56a99984209dad503d15dc0616ba2432853dd0e /container
parent423808ac767ed3a410948bf9e5df7b0da8d9e9c1 (diff)
container/check: intern absolute pathnames
This improves performance in heavy users like internal/pkg. Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'container')
-rw-r--r--container/check/absolute.go49
1 files changed, 37 insertions, 12 deletions
diff --git a/container/check/absolute.go b/container/check/absolute.go
index fcb260c5..26f0def6 100644
--- a/container/check/absolute.go
+++ b/container/check/absolute.go
@@ -9,6 +9,7 @@ import (
"slices"
"strings"
"syscall"
+ "unique"
)
// AbsoluteError is returned by [NewAbs] and holds the invalid pathname.
@@ -24,25 +25,35 @@ func (e *AbsoluteError) Is(target error) bool {
}
// Absolute holds a pathname checked to be absolute.
-type Absolute struct{ pathname string }
+type Absolute struct{ pathname unique.Handle[string] }
+
+// ok returns whether [Absolute] is not the zero value.
+func (a *Absolute) ok() bool { return a != nil && *a != (Absolute{}) }
// unsafeAbs returns [check.Absolute] on any string value.
-func unsafeAbs(pathname string) *Absolute { return &Absolute{pathname} }
+func unsafeAbs(pathname string) *Absolute {
+ return &Absolute{unique.Make(pathname)}
+}
+// String returns the checked pathname.
func (a *Absolute) String() string {
- if a.pathname == "" {
+ if !a.ok() {
panic("attempted use of zero Absolute")
}
+ return a.pathname.Value()
+}
+
+// Handle returns the underlying [unique.Handle].
+func (a *Absolute) Handle() unique.Handle[string] {
return a.pathname
}
+// Is efficiently compares the underlying pathname.
func (a *Absolute) Is(v *Absolute) bool {
if a == nil && v == nil {
return true
}
- return a != nil && v != nil &&
- a.pathname != "" && v.pathname != "" &&
- a.pathname == v.pathname
+ return a.ok() && v.ok() && a.pathname == v.pathname
}
// NewAbs checks pathname and returns a new [Absolute] if pathname is absolute.
@@ -70,17 +81,27 @@ func (a *Absolute) Append(elem ...string) *Absolute {
// Dir calls [path.Dir] with [Absolute] as its argument.
func (a *Absolute) Dir() *Absolute { return unsafeAbs(path.Dir(a.String())) }
-func (a *Absolute) GobEncode() ([]byte, error) { return []byte(a.String()), nil }
+// GobEncode returns the checked pathname.
+func (a *Absolute) GobEncode() ([]byte, error) {
+ return []byte(a.String()), nil
+}
+
+// GobDecode stores data if it represents an absolute pathname.
func (a *Absolute) GobDecode(data []byte) error {
pathname := string(data)
if !path.IsAbs(pathname) {
return &AbsoluteError{pathname}
}
- a.pathname = pathname
+ a.pathname = unique.Make(pathname)
return nil
}
-func (a *Absolute) MarshalJSON() ([]byte, error) { return json.Marshal(a.String()) }
+// MarshalJSON returns a JSON representation of the checked pathname.
+func (a *Absolute) MarshalJSON() ([]byte, error) {
+ return json.Marshal(a.String())
+}
+
+// UnmarshalJSON stores data if it represents an absolute pathname.
func (a *Absolute) UnmarshalJSON(data []byte) error {
var pathname string
if err := json.Unmarshal(data, &pathname); err != nil {
@@ -89,16 +110,20 @@ func (a *Absolute) UnmarshalJSON(data []byte) error {
if !path.IsAbs(pathname) {
return &AbsoluteError{pathname}
}
- a.pathname = pathname
+ a.pathname = unique.Make(pathname)
return nil
}
// SortAbs calls [slices.SortFunc] for a slice of [Absolute].
func SortAbs(x []*Absolute) {
- slices.SortFunc(x, func(a, b *Absolute) int { return strings.Compare(a.String(), b.String()) })
+ slices.SortFunc(x, func(a, b *Absolute) int {
+ return strings.Compare(a.String(), b.String())
+ })
}
// CompactAbs calls [slices.CompactFunc] for a slice of [Absolute].
func CompactAbs(s []*Absolute) []*Absolute {
- return slices.CompactFunc(s, func(a *Absolute, b *Absolute) bool { return a.String() == b.String() })
+ return slices.CompactFunc(s, func(a *Absolute, b *Absolute) bool {
+ return a.Is(b)
+ })
}