package vfs import ( "path" "strings" "sync" ) const Separator = "/" func isRoot(filename string) bool { return path.Clean(filename) == Separator } func trimRelPath(p, t string) string { return strings.Trim(strings.TrimPrefix(p, t), "/") } // func clean(p string) string { // return path.Clean(Separator + strings.ReplaceAll(p, "\\", "/")) // } func AbsPath(p string) string { if p == "" || p[0] != '/' { return Separator + p } return p } func AddTrailSlash(p string) string { if p == "" || p[len(p)-1] != '/' { return p + Separator } return p } // OnceValueWOErr returns a function that invokes f only once and returns the value // returned by f . The returned function may be called concurrently. // // If f panics, the returned function will panic with the same value on every call. func OnceValueWOErr[T any](f func() (T, error)) func() (T, error) { var ( mu sync.Mutex isExecuted bool r1 T err error ) return func() (T, error) { mu.Lock() defer mu.Unlock() if isExecuted && err == nil { return r1, nil } r1, err = f() return r1, err } }