Documentation
¶
Overview ¶
Package entitypath provides filepath-like manipulation of wherehouse entity paths. Paths are sequences of segments joined by a separator (":"). A path with a leading separator is absolute (rooted at the entity tree root); one without is relative. The package is pure syntax — it never touches the DB.
Index ¶
- Constants
- Variables
- func ValidateSegment(name string) error
- type Path
- func (p Path) Ancestors() []Path
- func (p Path) Append(name string) (Path, error)
- func (p Path) Base() string
- func (p Path) Clean() Path
- func (p Path) Depth() int
- func (p Path) Dir() Path
- func (p Path) HasPrefix(other Path) bool
- func (p Path) IsAbs() bool
- func (p Path) IsAncestor(other Path) bool
- func (p Path) IsEmpty() bool
- func (p Path) IsRoot() bool
- func (p Path) Join(segments ...string) (Path, error)
- func (p Path) MarshalJSON() ([]byte, error)
- func (p Path) Rel(base Path) (Path, error)
- func (p Path) Segments() []string
- func (p Path) String() string
- func (p *Path) UnmarshalJSON(b []byte) error
- func (p Path) Walk(yield func(ancestor Path) bool)
- func (p Path) WalkSeq() iter.Seq[Path]
Examples ¶
Constants ¶
const Separator = ":"
Separator is the string between path segments.
Variables ¶
var ( // ErrInvalidPath is returned when a path string fails structural validation. ErrInvalidPath = errors.New("entitypath: invalid path") // ErrEmptySegment is returned when a segment is an empty string. ErrEmptySegment = errors.New("entitypath: empty segment") // ErrSegmentContainsSeparator is returned when a segment contains Separator. ErrSegmentContainsSeparator = errors.New("entitypath: segment contains separator") // ErrInvalidSegment is returned when a segment has leading/trailing whitespace // or contains control characters. ErrInvalidSegment = errors.New("entitypath: invalid segment") // ErrNotDescendant is returned by Rel when base is not an ancestor of p. ErrNotDescendant = errors.New("entitypath: not a descendant of base") )
Sentinel errors returned by entitypath functions. Use errors.Is to test.
var Root = Path(Separator)
Root is the canonical absolute root path: a leading separator with no segments.
Functions ¶
func ValidateSegment ¶
ValidateSegment returns an error if name is not a valid path segment. It rejects empty strings, strings containing Separator, strings with leading/trailing whitespace, and strings containing control characters.
Types ¶
type Path ¶
type Path string //nolint:recvcheck // UnmarshalJSON requires *Path to satisfy json.Unmarshaler; all other methods use value receivers by design
Path is a syntactic entity path. The zero value Path("") is the valid empty relative path. Paths with a leading Separator are absolute (rooted).
func AppendTo ¶ added in v0.5.2
AppendTo parses parent as a Path and appends leaf as a single segment. It is a convenience wrapper for the common pattern of building a child path from a stored string (e.g. a FullPathDisplay from the DB) and a leaf name.
func MustParse ¶
MustParse panics if s is not a valid path. Intended for test helpers and package-level vars only.
func New ¶
New builds a relative path from segments. Each segment is validated. New() with no arguments returns Path("").
func Parse ¶
Parse validates s and returns it as a Path. It does not Clean; invalid paths return ErrInvalidPath (wrapping a more specific inner error).
Example ¶
package main
import (
"fmt"
"github.com/asphaltbuffet/wherehouse/internal/entitypath"
)
func main() {
p, err := entitypath.Parse(":Garage:Shelf A")
if err != nil {
panic(err)
}
fmt.Println(p)
fmt.Println(p.IsAbs())
fmt.Println(p.Depth())
}
Output: :Garage:Shelf A true 2
func (Path) Ancestors ¶
Ancestors returns all ancestors of p from the root-most to the nearest, excluding p itself. Returns an empty slice for Root and Path("").
func (Path) Append ¶
Append appends exactly one segment to p. It is equivalent to Join with a single argument and is the dominant call shape (parent path + child name).
func (Path) Clean ¶
Clean collapses adjacent separators and trims a single trailing separator (except for Root). It is idempotent. It does not resolve "." or "..".
Example ¶
package main
import (
"fmt"
"github.com/asphaltbuffet/wherehouse/internal/entitypath"
)
func main() {
p := entitypath.Path("Foo::Bar:")
fmt.Println(p.Clean())
}
Output: Foo:Bar
func (Path) Depth ¶
Depth returns the number of segments. Root and the empty path both have depth 0.
func (Path) Dir ¶
Dir returns all but the last segment of p. Dir of a 1-segment absolute path returns Root; Dir of a 1-segment relative path returns Path(""). Dir of Root returns Root; Dir of Path("") returns Path("").
func (Path) HasPrefix ¶
HasPrefix reports whether p == other or other.IsAncestor(p). Useful for subtree containment checks.
func (Path) IsAncestor ¶
IsAncestor reports whether p is a strict proper ancestor of other. p.IsAncestor(p) is always false. Mismatched absolute/relative paths return false.
func (Path) IsRoot ¶
IsRoot reports whether p is the absolute root path (Separator with no segments).
func (Path) Join ¶
Join appends segments to p. Each segment is validated. Passing no segments returns p unchanged. An empty segment string is an error.
Example ¶
package main
import (
"fmt"
"github.com/asphaltbuffet/wherehouse/internal/entitypath"
)
func main() {
p := entitypath.MustParse(":Garage:Shelf A")
child, err := p.Join("Bin 3")
if err != nil {
panic(err)
}
fmt.Println(child)
fmt.Println(p.IsAncestor(child))
}
Output: :Garage:Shelf A:Bin 3 true
func (Path) MarshalJSON ¶
MarshalJSON emits the path as a JSON string.
func (Path) Rel ¶
Rel returns the path of p relative to base. base must be an ancestor of p or equal p. If base == p, the empty relative path is returned. If base is not an ancestor, ErrNotDescendant is returned.
Example ¶
package main
import (
"fmt"
"github.com/asphaltbuffet/wherehouse/internal/entitypath"
)
func main() {
base := entitypath.MustParse(":Garage")
child := entitypath.MustParse(":Garage:Shelf A:Bin 3")
rel, err := child.Rel(base)
if err != nil {
panic(err)
}
fmt.Println(rel)
}
Output: Shelf A:Bin 3
func (Path) Segments ¶
Segments returns the path segments. Never returns nil; empty paths and Root return an empty slice.
func (*Path) UnmarshalJSON ¶
UnmarshalJSON accepts a JSON string and validates it via Parse. The pointer receiver is required to satisfy json.Unmarshaler.
func (Path) Walk ¶
Walk yields ancestors of p nearest-first (closest ancestor first), excluding p itself. Stops if yield returns false. Yields nothing for Root and Path(""). The range-over-func signature supports Go 1.23+ range loops.
Example ¶
package main
import (
"fmt"
"github.com/asphaltbuffet/wherehouse/internal/entitypath"
)
func main() {
p := entitypath.MustParse(":Garage:Shelf A:Bin 3")
p.Walk(func(a entitypath.Path) bool {
fmt.Println(a)
return true
})
}
Output: :Garage:Shelf A :Garage :