All checks were successful
		
		
	
	Test / Create distribution (push) Successful in 34s
				
			Test / Hpkg (push) Successful in 4m3s
				
			Test / Sandbox (race detector) (push) Successful in 4m26s
				
			Test / Hakurei (race detector) (push) Successful in 5m19s
				
			Test / Sandbox (push) Successful in 1m28s
				
			Test / Hakurei (push) Successful in 2m16s
				
			Test / Flake checks (push) Successful in 1m37s
				
			This allows use of absolute pathname values without importing container. Signed-off-by: Ophestra <cat@gensokyo.uk>
		
			
				
	
	
		
			105 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			105 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Package check provides types yielding values checked to meet a condition.
 | 
						|
package check
 | 
						|
 | 
						|
import (
 | 
						|
	"encoding/json"
 | 
						|
	"errors"
 | 
						|
	"fmt"
 | 
						|
	"path"
 | 
						|
	"slices"
 | 
						|
	"strings"
 | 
						|
	"syscall"
 | 
						|
)
 | 
						|
 | 
						|
// AbsoluteError is returned by [NewAbs] and holds the invalid pathname.
 | 
						|
type AbsoluteError struct{ Pathname string }
 | 
						|
 | 
						|
func (e *AbsoluteError) Error() string { return fmt.Sprintf("path %q is not absolute", e.Pathname) }
 | 
						|
func (e *AbsoluteError) Is(target error) bool {
 | 
						|
	var ce *AbsoluteError
 | 
						|
	if !errors.As(target, &ce) {
 | 
						|
		return errors.Is(target, syscall.EINVAL)
 | 
						|
	}
 | 
						|
	return *e == *ce
 | 
						|
}
 | 
						|
 | 
						|
// Absolute holds a pathname checked to be absolute.
 | 
						|
type Absolute struct{ pathname string }
 | 
						|
 | 
						|
// unsafeAbs returns [check.Absolute] on any string value.
 | 
						|
func unsafeAbs(pathname string) *Absolute { return &Absolute{pathname} }
 | 
						|
 | 
						|
func (a *Absolute) String() string {
 | 
						|
	if a.pathname == "" {
 | 
						|
		panic("attempted use of zero Absolute")
 | 
						|
	}
 | 
						|
	return a.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
 | 
						|
}
 | 
						|
 | 
						|
// NewAbs checks pathname and returns a new [Absolute] if pathname is absolute.
 | 
						|
func NewAbs(pathname string) (*Absolute, error) {
 | 
						|
	if !path.IsAbs(pathname) {
 | 
						|
		return nil, &AbsoluteError{pathname}
 | 
						|
	}
 | 
						|
	return unsafeAbs(pathname), nil
 | 
						|
}
 | 
						|
 | 
						|
// MustAbs calls [NewAbs] and panics on error.
 | 
						|
func MustAbs(pathname string) *Absolute {
 | 
						|
	if a, err := NewAbs(pathname); err != nil {
 | 
						|
		panic(err.Error())
 | 
						|
	} else {
 | 
						|
		return a
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// Append calls [path.Join] with [Absolute] as the first element.
 | 
						|
func (a *Absolute) Append(elem ...string) *Absolute {
 | 
						|
	return unsafeAbs(path.Join(append([]string{a.String()}, elem...)...))
 | 
						|
}
 | 
						|
 | 
						|
// 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 }
 | 
						|
func (a *Absolute) GobDecode(data []byte) error {
 | 
						|
	pathname := string(data)
 | 
						|
	if !path.IsAbs(pathname) {
 | 
						|
		return &AbsoluteError{pathname}
 | 
						|
	}
 | 
						|
	a.pathname = pathname
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (a *Absolute) MarshalJSON() ([]byte, error) { return json.Marshal(a.String()) }
 | 
						|
func (a *Absolute) UnmarshalJSON(data []byte) error {
 | 
						|
	var pathname string
 | 
						|
	if err := json.Unmarshal(data, &pathname); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	if !path.IsAbs(pathname) {
 | 
						|
		return &AbsoluteError{pathname}
 | 
						|
	}
 | 
						|
	a.pathname = 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()) })
 | 
						|
}
 | 
						|
 | 
						|
// 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() })
 | 
						|
}
 |