add value vithh error (#1)
Co-authored-by: andrey1s <andrey@4devs.pro> Reviewed-on: #1 Co-authored-by: andrey <andrey@4devs.io> Co-committed-by: andrey <andrey@4devs.io>
This commit was merged in pull request #1.
This commit is contained in:
10
input/variable/argtype.go
Normal file
10
input/variable/argtype.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package variable
|
||||
|
||||
//go:generate stringer -type=ArgType -linecomment
|
||||
|
||||
type ArgType int
|
||||
|
||||
const (
|
||||
TypeOption ArgType = iota + 1 // option
|
||||
TypeArgument // argument
|
||||
)
|
||||
25
input/variable/argtype_string.go
Normal file
25
input/variable/argtype_string.go
Normal file
@@ -0,0 +1,25 @@
|
||||
// Code generated by "stringer -type=ArgType -linecomment"; DO NOT EDIT.
|
||||
|
||||
package variable
|
||||
|
||||
import "strconv"
|
||||
|
||||
func _() {
|
||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||
// Re-run the stringer command to generate them again.
|
||||
var x [1]struct{}
|
||||
_ = x[TypeOption-1]
|
||||
_ = x[TypeArgument-2]
|
||||
}
|
||||
|
||||
const _ArgType_name = "optionargument"
|
||||
|
||||
var _ArgType_index = [...]uint8{0, 6, 14}
|
||||
|
||||
func (i ArgType) String() string {
|
||||
i -= 1
|
||||
if i < 0 || i >= ArgType(len(_ArgType_index)-1) {
|
||||
return "ArgType(" + strconv.FormatInt(int64(i+1), 10) + ")"
|
||||
}
|
||||
return _ArgType_name[_ArgType_index[i]:_ArgType_index[i+1]]
|
||||
}
|
||||
31
input/variable/bool.go
Normal file
31
input/variable/bool.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package variable
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"gitoa.ru/go-4devs/console/input/flag"
|
||||
"gitoa.ru/go-4devs/console/input/value"
|
||||
)
|
||||
|
||||
func Bool(name, description string, opts ...Option) Variable {
|
||||
return String(name, description, append(opts, WithParse(CreateBool, AppendBool), Value(flag.Bool))...)
|
||||
}
|
||||
|
||||
func CreateBool(in string) (value.Value, error) {
|
||||
out, err := strconv.ParseBool(in)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create bool:%w", err)
|
||||
}
|
||||
|
||||
return value.NewBool(out), nil
|
||||
}
|
||||
|
||||
func AppendBool(old value.Value, in string) (value.Value, error) {
|
||||
out, err := strconv.ParseBool(in)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create bool:%w", err)
|
||||
}
|
||||
|
||||
return value.NewBools(append(old.Bools(), out)), nil
|
||||
}
|
||||
31
input/variable/duration.go
Normal file
31
input/variable/duration.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package variable
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"gitoa.ru/go-4devs/console/input/flag"
|
||||
"gitoa.ru/go-4devs/console/input/value"
|
||||
)
|
||||
|
||||
func Duration(name, description string, opts ...Option) Variable {
|
||||
return String(name, description, append(opts, WithParse(CreateDuration, AppendDuration), Value(flag.Duration))...)
|
||||
}
|
||||
|
||||
func CreateDuration(in string) (value.Value, error) {
|
||||
out, err := time.ParseDuration(in)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create duration:%w", err)
|
||||
}
|
||||
|
||||
return value.NewDuration(out), nil
|
||||
}
|
||||
|
||||
func AppendDuration(old value.Value, in string) (value.Value, error) {
|
||||
out, err := time.ParseDuration(in)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("append duration:%w", err)
|
||||
}
|
||||
|
||||
return value.NewDurations(append(old.Durations(), out)), nil
|
||||
}
|
||||
32
input/variable/err.go
Normal file
32
input/variable/err.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package variable
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type Error struct {
|
||||
Name string
|
||||
Err error
|
||||
Type ArgType
|
||||
}
|
||||
|
||||
func (o Error) Error() string {
|
||||
return fmt.Sprintf("%s: '%s' %s", o.Type, o.Name, o.Err)
|
||||
}
|
||||
|
||||
func (o Error) Is(err error) bool {
|
||||
return errors.Is(err, o.Err)
|
||||
}
|
||||
|
||||
func (o Error) Unwrap() error {
|
||||
return o.Err
|
||||
}
|
||||
|
||||
func Err(name string, t ArgType, err error) Error {
|
||||
return Error{
|
||||
Name: name,
|
||||
Type: t,
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
31
input/variable/float64.go
Normal file
31
input/variable/float64.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package variable
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"gitoa.ru/go-4devs/console/input/flag"
|
||||
"gitoa.ru/go-4devs/console/input/value"
|
||||
)
|
||||
|
||||
func Float64(name, description string, opts ...Option) Variable {
|
||||
return String(name, description, append(opts, WithParse(CreateFloat64, AppendFloat64), Value(flag.Float64))...)
|
||||
}
|
||||
|
||||
func CreateFloat64(in string) (value.Value, error) {
|
||||
out, err := strconv.ParseFloat(in, 10)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create float64:%w", err)
|
||||
}
|
||||
|
||||
return value.NewFloat64(out), nil
|
||||
}
|
||||
|
||||
func AppendFloat64(old value.Value, in string) (value.Value, error) {
|
||||
out, err := strconv.ParseFloat(in, 10)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("append float64:%w", err)
|
||||
}
|
||||
|
||||
return value.NewFloat64s(append(old.Float64s(), out)), nil
|
||||
}
|
||||
31
input/variable/int.go
Normal file
31
input/variable/int.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package variable
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"gitoa.ru/go-4devs/console/input/flag"
|
||||
"gitoa.ru/go-4devs/console/input/value"
|
||||
)
|
||||
|
||||
func Int(name, description string, opts ...Option) Variable {
|
||||
return New(name, description, append(opts, WithParse(CreateInt, AppendInt), Value(flag.Int))...)
|
||||
}
|
||||
|
||||
func AppendInt(old value.Value, in string) (value.Value, error) {
|
||||
out, err := strconv.Atoi(in)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("append int:%w", err)
|
||||
}
|
||||
|
||||
return value.NewInts(append(old.Ints(), out)), nil
|
||||
}
|
||||
|
||||
func CreateInt(in string) (value.Value, error) {
|
||||
out, err := strconv.Atoi(in)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create int:%w", err)
|
||||
}
|
||||
|
||||
return value.NewInt(out), nil
|
||||
}
|
||||
31
input/variable/int64.go
Normal file
31
input/variable/int64.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package variable
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"gitoa.ru/go-4devs/console/input/flag"
|
||||
"gitoa.ru/go-4devs/console/input/value"
|
||||
)
|
||||
|
||||
func Int64(name, description string, opts ...Option) Variable {
|
||||
return String(name, description, append(opts, WithParse(CreateInt64, AppendInt64), Value(flag.Int64))...)
|
||||
}
|
||||
|
||||
func CreateInt64(in string) (value.Value, error) {
|
||||
out, err := strconv.ParseInt(in, 10, 64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create int64:%w", err)
|
||||
}
|
||||
|
||||
return value.NewInt64(out), nil
|
||||
}
|
||||
|
||||
func AppendInt64(old value.Value, in string) (value.Value, error) {
|
||||
out, err := strconv.ParseInt(in, 10, 64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("append int64:%w", err)
|
||||
}
|
||||
|
||||
return value.NewInt64s(append(old.Int64s(), out)), nil
|
||||
}
|
||||
17
input/variable/string.go
Normal file
17
input/variable/string.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package variable
|
||||
|
||||
import (
|
||||
"gitoa.ru/go-4devs/console/input/value"
|
||||
)
|
||||
|
||||
func String(name, description string, opts ...Option) Variable {
|
||||
return New(name, description, opts...)
|
||||
}
|
||||
|
||||
func CreateString(in string) (value.Value, error) {
|
||||
return value.NewString(in), nil
|
||||
}
|
||||
|
||||
func AppendString(old value.Value, in string) (value.Value, error) {
|
||||
return value.NewStrings(append(old.Strings(), in)), nil
|
||||
}
|
||||
77
input/variable/time.go
Normal file
77
input/variable/time.go
Normal file
@@ -0,0 +1,77 @@
|
||||
package variable
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"gitoa.ru/go-4devs/console/input/errs"
|
||||
"gitoa.ru/go-4devs/console/input/flag"
|
||||
"gitoa.ru/go-4devs/console/input/value"
|
||||
)
|
||||
|
||||
const (
|
||||
ParamFormat = "format"
|
||||
)
|
||||
|
||||
func Time(name, description string, opts ...Option) Variable {
|
||||
return String(name, description, append(opts,
|
||||
WithParamParse(CreateTime, AppendTime),
|
||||
WithParam(ParamFormat, RFC3339),
|
||||
Value(flag.Time),
|
||||
)...)
|
||||
}
|
||||
|
||||
func RFC3339(in interface{}) error {
|
||||
v, ok := in.(*string)
|
||||
if !ok {
|
||||
return fmt.Errorf("%w: expect *string got %T", errs.ErrWrongType, in)
|
||||
}
|
||||
|
||||
*v = time.RFC3339
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func CreateTime(param Param) Create {
|
||||
var (
|
||||
formatErr error
|
||||
format string
|
||||
)
|
||||
|
||||
formatErr = param.Value(ParamFormat, &format)
|
||||
|
||||
return func(in string) (value.Value, error) {
|
||||
if formatErr != nil {
|
||||
return nil, fmt.Errorf("create format:%w", formatErr)
|
||||
}
|
||||
|
||||
out, err := time.Parse(format, in)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create time:%w", err)
|
||||
}
|
||||
|
||||
return value.NewTime(out), nil
|
||||
}
|
||||
}
|
||||
|
||||
func AppendTime(param Param) Append {
|
||||
var (
|
||||
formatErr error
|
||||
format string
|
||||
)
|
||||
|
||||
formatErr = param.Value(ParamFormat, &format)
|
||||
|
||||
return func(old value.Value, in string) (value.Value, error) {
|
||||
if formatErr != nil {
|
||||
return nil, fmt.Errorf("append format:%w", formatErr)
|
||||
}
|
||||
|
||||
out, err := time.Parse(format, in)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("append time:%w", err)
|
||||
}
|
||||
|
||||
return value.NewTimes(append(old.Times(), out)), nil
|
||||
}
|
||||
}
|
||||
31
input/variable/uint.go
Normal file
31
input/variable/uint.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package variable
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"gitoa.ru/go-4devs/console/input/flag"
|
||||
"gitoa.ru/go-4devs/console/input/value"
|
||||
)
|
||||
|
||||
func Uint(name, description string, opts ...Option) Variable {
|
||||
return String(name, description, append(opts, WithParse(CreateUint, AppendUint), Value(flag.Uint))...)
|
||||
}
|
||||
|
||||
func CreateUint(in string) (value.Value, error) {
|
||||
out, err := strconv.ParseUint(in, 10, 64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create uint:%w", err)
|
||||
}
|
||||
|
||||
return value.NewUint(uint(out)), nil
|
||||
}
|
||||
|
||||
func AppendUint(old value.Value, in string) (value.Value, error) {
|
||||
out, err := strconv.ParseUint(in, 10, 64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("append uint:%w", err)
|
||||
}
|
||||
|
||||
return value.NewUints(append(old.Uints(), uint(out))), nil
|
||||
}
|
||||
31
input/variable/uint64.go
Normal file
31
input/variable/uint64.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package variable
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"gitoa.ru/go-4devs/console/input/flag"
|
||||
"gitoa.ru/go-4devs/console/input/value"
|
||||
)
|
||||
|
||||
func Uint64(name, descriontion string, opts ...Option) Variable {
|
||||
return String(name, descriontion, append(opts, WithParse(CreateUint64, AppendUint64), Value(flag.Uint64))...)
|
||||
}
|
||||
|
||||
func CreateUint64(in string) (value.Value, error) {
|
||||
out, err := strconv.ParseUint(in, 10, 64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create uint64:%w", err)
|
||||
}
|
||||
|
||||
return value.NewUint64(out), nil
|
||||
}
|
||||
|
||||
func AppendUint64(old value.Value, in string) (value.Value, error) {
|
||||
out, err := strconv.ParseUint(in, 10, 64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("append uint64:%w", err)
|
||||
}
|
||||
|
||||
return value.NewUint64s(append(old.Uint64s(), out)), nil
|
||||
}
|
||||
158
input/variable/variable.go
Normal file
158
input/variable/variable.go
Normal file
@@ -0,0 +1,158 @@
|
||||
package variable
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"gitoa.ru/go-4devs/console/input/errs"
|
||||
"gitoa.ru/go-4devs/console/input/flag"
|
||||
"gitoa.ru/go-4devs/console/input/value"
|
||||
)
|
||||
|
||||
type Option func(*Variable)
|
||||
|
||||
func WithType(t ArgType) Option {
|
||||
return func(v *Variable) {
|
||||
v.Type = t
|
||||
}
|
||||
}
|
||||
|
||||
func ArgOption(v *Variable) {
|
||||
v.Type = TypeOption
|
||||
}
|
||||
|
||||
func ArgArgument(v *Variable) {
|
||||
v.Type = TypeArgument
|
||||
}
|
||||
|
||||
func Value(in flag.Flag) Option {
|
||||
return func(v *Variable) {
|
||||
v.Flag |= in
|
||||
}
|
||||
}
|
||||
|
||||
func Default(in value.Value) Option {
|
||||
return func(v *Variable) {
|
||||
v.Default = in
|
||||
}
|
||||
}
|
||||
|
||||
func Required(v *Variable) {
|
||||
v.Flag |= flag.Required
|
||||
}
|
||||
|
||||
func WithParse(create Create, update Append) Option {
|
||||
return func(v *Variable) {
|
||||
v.append = func(Param) Append { return update }
|
||||
v.create = func(Param) Create { return create }
|
||||
}
|
||||
}
|
||||
|
||||
func WithParamParse(create func(Param) Create, update func(Param) Append) Option {
|
||||
return func(v *Variable) {
|
||||
v.append = update
|
||||
v.create = create
|
||||
}
|
||||
}
|
||||
|
||||
func Valid(f ...func(value.Value) error) Option {
|
||||
return func(v *Variable) {
|
||||
v.Valid = f
|
||||
}
|
||||
}
|
||||
|
||||
func Array(o *Variable) {
|
||||
o.Flag |= flag.Array
|
||||
}
|
||||
|
||||
func WithParam(name string, fn func(interface{}) error) Option {
|
||||
return func(v *Variable) {
|
||||
v.params[name] = fn
|
||||
}
|
||||
}
|
||||
|
||||
type (
|
||||
Create func(s string) (value.Value, error)
|
||||
Append func(old value.Value, s string) (value.Value, error)
|
||||
)
|
||||
|
||||
func New(name, description string, opts ...Option) Variable {
|
||||
res := Variable{
|
||||
Name: name,
|
||||
Description: description,
|
||||
Type: TypeOption,
|
||||
create: func(Param) Create { return CreateString },
|
||||
append: func(Param) Append { return AppendString },
|
||||
params: make(Params),
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
opt(&res)
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
type Variable struct {
|
||||
Name string
|
||||
Description string
|
||||
Alias string
|
||||
Flag flag.Flag
|
||||
Type ArgType
|
||||
Default value.Value
|
||||
Valid []func(value.Value) error
|
||||
params Params
|
||||
create func(Param) Create
|
||||
append func(Param) Append
|
||||
}
|
||||
|
||||
func (v Variable) Validate(in value.Value) error {
|
||||
for _, valid := range v.Valid {
|
||||
if err := valid(in); err != nil {
|
||||
return Err(v.Name, v.Type, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v Variable) IsArray() bool {
|
||||
return v.Flag.IsArray()
|
||||
}
|
||||
|
||||
func (v Variable) IsRequired() bool {
|
||||
return v.Flag.IsRequired()
|
||||
}
|
||||
|
||||
func (v Variable) HasDefault() bool {
|
||||
return v.Default != nil
|
||||
}
|
||||
|
||||
func (v Variable) IsBool() bool {
|
||||
return v.Flag.IsBool()
|
||||
}
|
||||
|
||||
func (v Variable) HasShort() bool {
|
||||
return v.Type == TypeOption && len(v.Alias) == 1
|
||||
}
|
||||
|
||||
func (v Variable) Create(s string) (value.Value, error) {
|
||||
return v.create(v.params)(s)
|
||||
}
|
||||
|
||||
func (v Variable) Append(old value.Value, s string) (value.Value, error) {
|
||||
return v.append(v.params)(old, s)
|
||||
}
|
||||
|
||||
type Param interface {
|
||||
Value(name string, v interface{}) error
|
||||
}
|
||||
|
||||
type Params map[string]func(interface{}) error
|
||||
|
||||
func (p Params) Value(name string, v interface{}) error {
|
||||
if p, ok := p[name]; ok {
|
||||
return p(v)
|
||||
}
|
||||
|
||||
return fmt.Errorf("%w: param %v", errs.ErrNotFound, name)
|
||||
}
|
||||
Reference in New Issue
Block a user