mirror of
https://github.com/IBM/fp-go.git
synced 2025-08-10 22:31:32 +02:00
fix: remove types from this branch
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
This commit is contained in:
@@ -98,7 +98,7 @@ func MapRefWithIndex[K comparable, V, R any](f func(K, *V) R) func(map[K]V) map[
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Lookup returns the entry for a key in a map if it exists
|
// Lookup returns the entry for a key in a map if it exists
|
||||||
func Lookup[K comparable, V any](k K) func(map[K]V) O.Option[V] {
|
func Lookup[V any, K comparable](k K) func(map[K]V) O.Option[V] {
|
||||||
return G.Lookup[map[K]V](k)
|
return G.Lookup[map[K]V](k)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -71,8 +71,8 @@ func TestLookup(t *testing.T) {
|
|||||||
"b": "b",
|
"b": "b",
|
||||||
"c": "c",
|
"c": "c",
|
||||||
}
|
}
|
||||||
assert.Equal(t, O.Some("a"), Lookup[string, string]("a")(data))
|
assert.Equal(t, O.Some("a"), Lookup[string]("a")(data))
|
||||||
assert.Equal(t, O.None[string](), Lookup[string, string]("a1")(data))
|
assert.Equal(t, O.None[string](), Lookup[string]("a1")(data))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFilterChain(t *testing.T) {
|
func TestFilterChain(t *testing.T) {
|
||||||
|
@@ -1,91 +0,0 @@
|
|||||||
// Copyright (c) 2023 IBM Corp.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package types
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"reflect"
|
|
||||||
|
|
||||||
AR "github.com/IBM/fp-go/array/generic"
|
|
||||||
E "github.com/IBM/fp-go/either"
|
|
||||||
F "github.com/IBM/fp-go/function"
|
|
||||||
T "github.com/IBM/fp-go/tuple"
|
|
||||||
)
|
|
||||||
|
|
||||||
func toUnknownArray[A any](item func(reflect.Value, Context) E.Either[Errors, A], c Context, val reflect.Value) []E.Either[Errors, A] {
|
|
||||||
l := val.Len()
|
|
||||||
res := make([]E.Either[Errors, A], l)
|
|
||||||
for i := l - 1; i >= 0; i-- {
|
|
||||||
v := val.Index(i)
|
|
||||||
res[i] = item(v, AR.Push[Context](&ContextEntry{Key: fmt.Sprintf("[%d]", i), Value: v})(c))
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
func flattenUnknownArray[GA ~[]A, A any](as []E.Either[Errors, A]) E.Either[Errors, GA] {
|
|
||||||
return F.Pipe1(
|
|
||||||
AR.Reduce(as, func(t T.Tuple2[GA, Errors], item E.Either[Errors, A]) T.Tuple2[GA, Errors] {
|
|
||||||
return E.MonadFold(item, func(e Errors) T.Tuple2[GA, Errors] {
|
|
||||||
return T.MakeTuple2(t.F1, append(t.F2, e...))
|
|
||||||
}, func(a A) T.Tuple2[GA, Errors] {
|
|
||||||
return T.MakeTuple2(append(t.F1, a), t.F2)
|
|
||||||
})
|
|
||||||
}, T.MakeTuple2(make(GA, len(as)), make(Errors, 0))),
|
|
||||||
func(t T.Tuple2[GA, Errors]) E.Either[Errors, GA] {
|
|
||||||
if AR.IsEmpty(t.F2) {
|
|
||||||
return E.Of[Errors](t.F1)
|
|
||||||
}
|
|
||||||
return E.Left[GA](t.F2)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func toValidatedArray[GA ~[]A, A any](item func(reflect.Value, Context) E.Either[Errors, A], c Context, val reflect.Value) E.Either[Errors, GA] {
|
|
||||||
return F.Pipe1(
|
|
||||||
toUnknownArray(item, c, val),
|
|
||||||
flattenUnknownArray[GA, A],
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func validateArray[GA ~[]A, A any](item Validate[reflect.Value, A]) func(i reflect.Value, c Context) E.Either[Errors, GA] {
|
|
||||||
var r func(i reflect.Value, c Context) E.Either[Errors, GA]
|
|
||||||
|
|
||||||
r = func(i reflect.Value, c Context) E.Either[Errors, GA] {
|
|
||||||
// check for unknow array
|
|
||||||
switch i.Kind() {
|
|
||||||
case reflect.Slice:
|
|
||||||
return toValidatedArray[GA](item, c, i)
|
|
||||||
case reflect.Array:
|
|
||||||
return toValidatedArray[GA](item, c, i)
|
|
||||||
case reflect.Pointer:
|
|
||||||
return r(i.Elem(), c)
|
|
||||||
default:
|
|
||||||
return Failure[GA](c, fmt.Sprintf("Type %T is neither an array nor a slice nor a pointer to these values", i))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
// ArrayG returns the type validator for an array
|
|
||||||
func ArrayG[GA ~[]A, A any](item Validate[reflect.Value, A]) *Type[GA, GA, reflect.Value] {
|
|
||||||
return FromValidate(validateArray[GA, A](item))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Array returns the type validator for an array
|
|
||||||
func Array[A any](item Validate[reflect.Value, A]) *Type[[]A, []A, reflect.Value] {
|
|
||||||
return ArrayG[[]A, A](item)
|
|
||||||
}
|
|
@@ -1,41 +0,0 @@
|
|||||||
// Copyright (c) 2023 IBM Corp.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package types
|
|
||||||
|
|
||||||
import (
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
A "github.com/IBM/fp-go/array"
|
|
||||||
E "github.com/IBM/fp-go/either"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestArray(t *testing.T) {
|
|
||||||
stringArray := Array(String.Validate)
|
|
||||||
|
|
||||||
validData := A.From(
|
|
||||||
reflect.ValueOf(A.From("a", "b", "c")),
|
|
||||||
reflect.ValueOf(A.Empty[string]()),
|
|
||||||
reflect.ValueOf([]string{"a", "b"}),
|
|
||||||
reflect.ValueOf(A.From(1, 2, 3)),
|
|
||||||
)
|
|
||||||
|
|
||||||
for i := 0; i < len(validData); i++ {
|
|
||||||
assert.True(t, E.IsRight(stringArray.Decode(validData[i])))
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,16 +0,0 @@
|
|||||||
// Copyright (c) 2023 IBM Corp.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package types
|
|
@@ -1,39 +0,0 @@
|
|||||||
// Copyright (c) 2023 IBM Corp.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package types
|
|
||||||
|
|
||||||
import (
|
|
||||||
AR "github.com/IBM/fp-go/array/generic"
|
|
||||||
E "github.com/IBM/fp-go/either"
|
|
||||||
)
|
|
||||||
|
|
||||||
func getMessage(val *ValidationError) string {
|
|
||||||
return val.Message
|
|
||||||
}
|
|
||||||
|
|
||||||
func pathNoErrors() []string {
|
|
||||||
return AR.Of[[]string]("No Errors!")
|
|
||||||
}
|
|
||||||
|
|
||||||
func PathReporter[A any](val E.Either[Errors, A]) []string {
|
|
||||||
return E.MonadFold(
|
|
||||||
val,
|
|
||||||
AR.Map[Errors, []string](getMessage),
|
|
||||||
func(_ A) []string {
|
|
||||||
return pathNoErrors()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
@@ -1,57 +0,0 @@
|
|||||||
// Copyright (c) 2023 IBM Corp.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package types
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"reflect"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
E "github.com/IBM/fp-go/either"
|
|
||||||
)
|
|
||||||
|
|
||||||
func validateStringFromReflect(i reflect.Value, c Context) E.Either[Errors, string] {
|
|
||||||
switch i.Kind() {
|
|
||||||
case reflect.String:
|
|
||||||
return E.Of[Errors](i.String())
|
|
||||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
||||||
return E.Of[Errors](strconv.FormatInt(i.Int(), 10))
|
|
||||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
|
||||||
return E.Of[Errors](strconv.FormatUint(i.Uint(), 10))
|
|
||||||
case reflect.Bool:
|
|
||||||
return E.Of[Errors](strconv.FormatBool(i.Bool()))
|
|
||||||
case reflect.Pointer:
|
|
||||||
return validateStringFromReflect(i.Elem(), c)
|
|
||||||
case reflect.Invalid:
|
|
||||||
return Failure[string](c, "Invalid value")
|
|
||||||
}
|
|
||||||
|
|
||||||
if i.CanInterface() {
|
|
||||||
if strg, ok := i.Interface().(fmt.Stringer); ok {
|
|
||||||
return E.Of[Errors](strg.String())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return E.Of[Errors](i.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns the type validator for a string
|
|
||||||
func makeString() *Type[string, string, reflect.Value] {
|
|
||||||
return FromValidate(validateStringFromReflect)
|
|
||||||
}
|
|
||||||
|
|
||||||
// converts from any type to string
|
|
||||||
var String = makeString()
|
|
@@ -1,47 +0,0 @@
|
|||||||
// Copyright (c) 2023 IBM Corp.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package types
|
|
||||||
|
|
||||||
import (
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
A "github.com/IBM/fp-go/array"
|
|
||||||
E "github.com/IBM/fp-go/either"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestString(t *testing.T) {
|
|
||||||
s := "Carsten"
|
|
||||||
validData := A.From(
|
|
||||||
reflect.ValueOf("Carsten"),
|
|
||||||
reflect.ValueOf(s),
|
|
||||||
reflect.ValueOf(&s),
|
|
||||||
reflect.ValueOf(10),
|
|
||||||
reflect.ValueOf(true),
|
|
||||||
reflect.ValueOf(false),
|
|
||||||
)
|
|
||||||
for i := 0; i < len(validData); i++ {
|
|
||||||
assert.True(t, E.IsRight(String.Decode(validData[i])))
|
|
||||||
}
|
|
||||||
|
|
||||||
invalidDataData := A.From(
|
|
||||||
reflect.ValueOf(nil),
|
|
||||||
)
|
|
||||||
for i := 0; i < len(invalidDataData); i++ {
|
|
||||||
assert.True(t, E.IsLeft(String.Decode(invalidDataData[i])))
|
|
||||||
}
|
|
||||||
}
|
|
146
types/types.go
146
types/types.go
@@ -1,146 +0,0 @@
|
|||||||
// Copyright (c) 2023 IBM Corp.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package types
|
|
||||||
|
|
||||||
import (
|
|
||||||
AR "github.com/IBM/fp-go/array/generic"
|
|
||||||
E "github.com/IBM/fp-go/either"
|
|
||||||
F "github.com/IBM/fp-go/function"
|
|
||||||
"github.com/IBM/fp-go/option"
|
|
||||||
)
|
|
||||||
|
|
||||||
type (
|
|
||||||
ValidationError struct {
|
|
||||||
Context Context
|
|
||||||
Message string
|
|
||||||
}
|
|
||||||
|
|
||||||
ContextEntry struct {
|
|
||||||
Key string
|
|
||||||
Value any
|
|
||||||
}
|
|
||||||
|
|
||||||
Errors []*ValidationError
|
|
||||||
|
|
||||||
Context []*ContextEntry
|
|
||||||
|
|
||||||
Encoder[A, O any] interface {
|
|
||||||
Encode(A) O
|
|
||||||
}
|
|
||||||
|
|
||||||
Decoder[I, A any] interface {
|
|
||||||
Validate(I, Context) E.Either[Errors, A]
|
|
||||||
Decode(I) E.Either[Errors, A]
|
|
||||||
}
|
|
||||||
|
|
||||||
Codec[I, O, A any] interface {
|
|
||||||
Encoder[A, O]
|
|
||||||
Decoder[I, A]
|
|
||||||
}
|
|
||||||
|
|
||||||
Guard[I, A any] func(I) option.Option[A]
|
|
||||||
|
|
||||||
Validate[I, A any] func(I, Context) E.Either[Errors, A]
|
|
||||||
|
|
||||||
Type[A, O, I any] struct {
|
|
||||||
validate func(I, Context) E.Either[Errors, A]
|
|
||||||
encode func(A) O
|
|
||||||
is Guard[I, A]
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func (t *Type[A, O, I]) Validate(i I, c Context) E.Either[Errors, A] {
|
|
||||||
return t.validate(i, c)
|
|
||||||
}
|
|
||||||
|
|
||||||
func defaultContext(value any) Context {
|
|
||||||
return AR.Of[Context](&ContextEntry{Value: value})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Type[A, O, I]) Decode(i I) E.Either[Errors, A] {
|
|
||||||
return t.validate(i, defaultContext(i))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Type[A, O, I]) Encode(a A) O {
|
|
||||||
return t.encode(a)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Type[A, O, I]) Is(a I) option.Option[A] {
|
|
||||||
return t.is(a)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Type[A, O, I]) AsEncoder() Encoder[A, O] {
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Type[A, O, I]) AsDecoder() Decoder[I, A] {
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
|
|
||||||
func (val *ValidationError) Error() string {
|
|
||||||
return val.Message
|
|
||||||
}
|
|
||||||
|
|
||||||
func Pipe[O, I, A, B any](ab Type[B, A, A]) func(a Type[A, O, I]) Type[B, O, I] {
|
|
||||||
return func(a Type[A, O, I]) Type[B, O, I] {
|
|
||||||
return Type[B, O, I]{
|
|
||||||
is: F.Flow2(
|
|
||||||
a.is,
|
|
||||||
option.Chain(ab.Is),
|
|
||||||
),
|
|
||||||
validate: func(i I, c Context) E.Either[Errors, B] {
|
|
||||||
return F.Pipe1(
|
|
||||||
a.Validate(i, c),
|
|
||||||
E.Chain(F.Bind2nd(ab.Validate, c)),
|
|
||||||
)
|
|
||||||
},
|
|
||||||
encode: F.Flow2(
|
|
||||||
ab.Encode,
|
|
||||||
a.Encode,
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Success[A any](value A) E.Either[Errors, A] {
|
|
||||||
return E.Of[Errors](value)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Failures[A any](err Errors) E.Either[Errors, A] {
|
|
||||||
return E.Left[A](err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Failure[A any](c Context, message string) E.Either[Errors, A] {
|
|
||||||
return Failures[A](AR.Of[Errors](&ValidationError{Context: c, Message: message}))
|
|
||||||
}
|
|
||||||
|
|
||||||
func guardFromValidate[A, I any](validate func(I, Context) E.Either[Errors, A]) Guard[I, A] {
|
|
||||||
return func(i I) option.Option[A] {
|
|
||||||
return F.Pipe1(
|
|
||||||
validate(i, defaultContext(i)),
|
|
||||||
E.ToOption[Errors, A],
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FromValidate constructs a Type instance from just the validation function
|
|
||||||
func FromValidate[A, I any](validate Validate[I, A]) *Type[A, A, I] {
|
|
||||||
return &Type[A, A, I]{
|
|
||||||
validate,
|
|
||||||
F.Identity[A],
|
|
||||||
guardFromValidate[A, I](validate),
|
|
||||||
}
|
|
||||||
}
|
|
Reference in New Issue
Block a user