command: simplify errors
This commit is contained in:
@@ -1,54 +1,11 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
separator = "/"
|
||||
)
|
||||
|
||||
// ErrNew indicates that the wrapped error was encountered while creating
|
||||
// a new Command.
|
||||
var ErrNew = errors.New("failed to create Command from elems")
|
||||
|
||||
// ErrParse indicates that the wrapped error was encountered while
|
||||
// attempting to parse a string as a Command.
|
||||
var ErrParse = errors.New("failed to parse Command")
|
||||
|
||||
// ErrorJoin indicates that the wrapped error was encountered while
|
||||
// attempting to join a new segment to a Command.
|
||||
var ErrJoin = errors.New("failed to join segments to Command")
|
||||
|
||||
// ErrRequiresLeadingSlash is returned when a parsing a string that
|
||||
// doesn't start with a [leading slash character].
|
||||
//
|
||||
// [leading slash character]: https://github.com/ucan-wg/spec#segment-structure
|
||||
var ErrRequiresLeadingSlash = parseError("a command requires a leading slash character")
|
||||
|
||||
// ErrDisallowsTrailingSlash is returned when parsing a string that [ends
|
||||
// with a trailing slash character].
|
||||
//
|
||||
// [ends with a trailing slash character]: https://github.com/ucan-wg/spec#segment-structure
|
||||
var ErrDisallowsTrailingSlash = parseError("a command must not include a trailing slash")
|
||||
|
||||
// ErrUCANNamespaceReserved is returned to indicate that a Command's
|
||||
// first segment would contain the [reserved "ucan" namespace].
|
||||
//
|
||||
// [reserved "ucan" namespace]: https://github.com/ucan-wg/spec#ucan-namespace
|
||||
var ErrUCANNamespaceReserved = errors.New("the UCAN namespace is reserved")
|
||||
|
||||
// ErrRequiresLowercase is returned if a Command contains, or would contain,
|
||||
// [uppercase unicode characters].
|
||||
//
|
||||
// [uppercase unicode characters]: https://github.com/ucan-wg/spec#segment-structure
|
||||
var ErrRequiresLowercase = parseError("UCAN path segments must must not contain upper-case characters")
|
||||
|
||||
func parseError(msg string) error {
|
||||
return fmt.Errorf("%w: %s", ErrParse, msg)
|
||||
}
|
||||
const separator = "/"
|
||||
|
||||
var _ fmt.Stringer = (*Command)(nil)
|
||||
|
||||
@@ -66,18 +23,8 @@ type Command struct {
|
||||
// New creates a validated command from the provided list of segment
|
||||
// strings. An error is returned if an invalid Command would be
|
||||
// formed
|
||||
func New(segments ...string) (*Command, error) {
|
||||
return newCommand(ErrNew, segments...)
|
||||
}
|
||||
|
||||
func newCommand(err error, segments ...string) (*Command, error) {
|
||||
if len(segments) > 0 && segments[0] == "ucan" {
|
||||
return nil, fmt.Errorf("%w: %w", err, ErrUCANNamespaceReserved)
|
||||
}
|
||||
|
||||
cmd := Command{segments}
|
||||
|
||||
return &cmd, nil
|
||||
func New(segments ...string) *Command {
|
||||
return &Command{segments: segments}
|
||||
}
|
||||
|
||||
// Parse verifies that the provided string contains the required
|
||||
@@ -100,7 +47,16 @@ func Parse(s string) (*Command, error) {
|
||||
|
||||
// The leading slash will result in the first element from strings.Split
|
||||
// being an empty string which is removed as strings.Join will ignore it.
|
||||
return newCommand(ErrParse, strings.Split(s, "/")[1:]...)
|
||||
return &Command{strings.Split(s, "/")[1:]}, nil
|
||||
}
|
||||
|
||||
// MustParse is the same as Parse, but panic() if the parsing fail.
|
||||
func MustParse(s string) *Command {
|
||||
c, err := Parse(s)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// [Top] is the most powerful capability.
|
||||
@@ -111,22 +67,19 @@ func Parse(s string) (*Command, error) {
|
||||
//
|
||||
// [Top]: https://github.com/ucan-wg/spec#-aka-top
|
||||
func Top() *Command {
|
||||
cmd, _ := New()
|
||||
|
||||
return cmd
|
||||
return New()
|
||||
}
|
||||
|
||||
// IsValid returns true if the provided string is a valid UCAN command.
|
||||
func IsValid(s string) bool {
|
||||
_, err := Parse(s)
|
||||
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// Join appends segments to the end of this command using the required
|
||||
// segment separator.
|
||||
func (c *Command) Join(segments ...string) (*Command, error) {
|
||||
return newCommand(ErrJoin, append(c.segments, segments...)...)
|
||||
func (c *Command) Join(segments ...string) *Command {
|
||||
return &Command{append(c.segments, segments...)}
|
||||
}
|
||||
|
||||
// Segments returns the ordered segments that comprise the Command as a
|
||||
@@ -138,5 +91,5 @@ func (c *Command) Segments() []string {
|
||||
// String returns the composed representation the command. This is also
|
||||
// the required wire representation (before IPLD encoding occurs.)
|
||||
func (c *Command) String() string {
|
||||
return "/" + strings.Join([]string(c.segments), "/")
|
||||
return "/" + strings.Join(c.segments, "/")
|
||||
}
|
||||
|
||||
21
capability/command/command_errors.go
Normal file
21
capability/command/command_errors.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package command
|
||||
|
||||
import "fmt"
|
||||
|
||||
// ErrRequiresLeadingSlash is returned when a parsing a string that
|
||||
// doesn't start with a [leading slash character].
|
||||
//
|
||||
// [leading slash character]: https://github.com/ucan-wg/spec#segment-structure
|
||||
var ErrRequiresLeadingSlash = fmt.Errorf("a command requires a leading slash character")
|
||||
|
||||
// ErrDisallowsTrailingSlash is returned when parsing a string that [ends
|
||||
// with a trailing slash character].
|
||||
//
|
||||
// [ends with a trailing slash character]: https://github.com/ucan-wg/spec#segment-structure
|
||||
var ErrDisallowsTrailingSlash = fmt.Errorf("a command must not include a trailing slash")
|
||||
|
||||
// ErrRequiresLowercase is returned if a Command contains, or would contain,
|
||||
// [uppercase unicode characters].
|
||||
//
|
||||
// [uppercase unicode characters]: https://github.com/ucan-wg/spec#segment-structure
|
||||
var ErrRequiresLowercase = fmt.Errorf("UCAN path segments must must not contain upper-case characters")
|
||||
@@ -73,7 +73,6 @@ func TestParseCommand(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
cmd, err := command.Parse(testcase.inp)
|
||||
require.ErrorIs(t, err, command.ErrParse)
|
||||
require.ErrorIs(t, err, testcase.err)
|
||||
require.Nil(t, cmd)
|
||||
})
|
||||
@@ -134,20 +133,6 @@ func invalidTestcases(t *testing.T) []errorTestcase {
|
||||
},
|
||||
err: command.ErrDisallowsTrailingSlash,
|
||||
},
|
||||
{
|
||||
testcase: testcase{
|
||||
name: "only reserved ucan namespace",
|
||||
inp: "/ucan",
|
||||
},
|
||||
err: command.ErrUCANNamespaceReserved,
|
||||
},
|
||||
{
|
||||
testcase: testcase{
|
||||
name: "reserved ucan namespace prefix",
|
||||
inp: "/ucan/elem0/elem1/elem2",
|
||||
},
|
||||
err: command.ErrUCANNamespaceReserved,
|
||||
},
|
||||
{
|
||||
testcase: testcase{
|
||||
name: "uppercase character are present",
|
||||
|
||||
Reference in New Issue
Block a user