Skip to content

Commit

Permalink
Add Map, MapValue and MapError to res package.
Browse files Browse the repository at this point in the history
  • Loading branch information
jpfourny committed Mar 22, 2024
1 parent 91f7237 commit 16658ea
Show file tree
Hide file tree
Showing 2 changed files with 218 additions and 0 deletions.
27 changes: 27 additions & 0 deletions pkg/res/result.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,30 @@ func Of[T any](val T, err error) Result[T] {
}
return OfSuccess[T](val)
}

// MapValue maps the value of the result to a new value using the provided mapper function.
// The error of the result, if any, is unchanged.
func MapValue[T, U any](r Result[T], valueMapper func(T) U) Result[U] {
errorMapper := func(err error) error { return err }
return Map[T, U](r, valueMapper, errorMapper)
}

// MapError maps the error of the result to a new error using the provided mapper function.
// The value of the result, if any, is unchanged.
func MapError[T any](r Result[T], errorMapper func(error) error) Result[T] {
valueMapper := func(val T) T { return val }
return Map[T, T](r, valueMapper, errorMapper)
}

// Map maps the result to a new result using the provided value and error mapper functions.
// The value mapper function maps the value of the result to a new value.
// The error mapper function maps the error of the result to a new error.
func Map[T, U any](r Result[T], valueMapper func(T) U, errorMapper func(error) error) Result[U] {
if r.Succeeded() {
return OfSuccess[U](valueMapper(r.Value().GetOrZero()))
}
if r.PartiallySucceeded() {
return OfPartialSuccess[U](valueMapper(r.Value().GetOrZero()), errorMapper(r.Error().GetOrZero()))
}
return OfFailure[U](errorMapper(r.Error().GetOrZero()))
}
191 changes: 191 additions & 0 deletions pkg/res/result_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package res

import (
"errors"
"fmt"
"testing"
)

Expand Down Expand Up @@ -146,3 +147,193 @@ func TestOf(t *testing.T) {
}
})
}

func TestMapValue(t *testing.T) {
t.Run("Success", func(t *testing.T) {
r := OfSuccess(42)
mapped := MapValue(r, func(val int) string {
return fmt.Sprintf("%d", val)
})
if !mapped.Succeeded() {
t.Errorf("expected Succeeded() to be true")
}
if mapped.PartiallySucceeded() {
t.Errorf("expected PartiallySucceeded() to be false")
}
if mapped.Failed() {
t.Errorf("expected Failed() to be false")
}
if !mapped.HasValue() {
t.Errorf("expected HasValue() to be true")
}
if mapped.HasError() {
t.Errorf("expected HasError() to be false")
}
if mapped.Value().GetOrZero() != "42" {
t.Errorf("expected Value() to return 42")
}
if mapped.Error().Present() {
t.Errorf("expected Error() to be empty")
}
if mapped.String() != "Success(\"42\")" {
t.Errorf("expected String() to return Success(\"42\")")
}
})

t.Run("Failure", func(t *testing.T) {
r := OfFailure[int](errors.New("error"))
mapped := MapValue(r, func(val int) string {
return fmt.Sprintf("%d", val)
})
if mapped.Succeeded() {
t.Errorf("expected Succeeded() to be false")
}
if mapped.PartiallySucceeded() {
t.Errorf("expected PartiallySucceeded() to be false")
}
if !mapped.Failed() {
t.Errorf("expected Failed() to be true")
}
if mapped.HasValue() {
t.Errorf("expected HasValue() to be false")
}
if !mapped.HasError() {
t.Errorf("expected HasError() to be true")
}
if mapped.Error().GetOrZero().Error() != "error" {
t.Errorf("expected Error() to return error")
}
if mapped.Value().Present() {
t.Errorf("expected Value() to be empty")
}
if mapped.String() != "Failure(error)" {
t.Errorf("expected String() to return Failure(error)")
}
})

t.Run("PartialSuccess", func(t *testing.T) {
r := OfPartialSuccess(42, errors.New("error"))
mapped := MapValue(r, func(val int) string {
return fmt.Sprintf("%d", val)
})
if mapped.Succeeded() {
t.Errorf("expected Succeeded() to be false")
}
if !mapped.PartiallySucceeded() {
t.Errorf("expected PartiallySucceeded() to be true")
}
if mapped.Failed() {
t.Errorf("expected Failed() to be false")
}
if !mapped.HasValue() {
t.Errorf("expected HasValue() to be true")
}
if !mapped.HasError() {
t.Errorf("expected HasError() to be true")
}
if mapped.Value().GetOrZero() != "42" {
t.Errorf("expected Value() to return 42")
}
if !mapped.Error().Present() {
t.Errorf("expected Error() to be non-empty")
}
if mapped.String() != "PartialSuccess(\"42\", error)" {
t.Errorf("expected String() to return PartialSuccess(\"42\", error)")
}
})
}

func TestMapError(t *testing.T) {
t.Run("Success", func(t *testing.T) {
r := OfSuccess(42)
mapped := MapError(r, func(err error) error {
return errors.New("mapped error")
})
if !mapped.Succeeded() {
t.Errorf("expected Succeeded() to be true")
}
if mapped.PartiallySucceeded() {
t.Errorf("expected PartiallySucceeded() to be false")
}
if mapped.Failed() {
t.Errorf("expected Failed() to be false")
}
if !mapped.HasValue() {
t.Errorf("expected HasValue() to be true")
}
if mapped.HasError() {
t.Errorf("expected HasError() to be false")
}
if mapped.Value().GetOrZero() != 42 {
t.Errorf("expected Value() to return 42")
}
if mapped.Error().Present() {
t.Errorf("expected Error() to be empty")
}
if mapped.String() != "Success(42)" {
t.Errorf("expected String() to return Success(42)")
}
})

t.Run("Failure", func(t *testing.T) {
r := OfFailure[int](errors.New("error"))
mapped := MapError(r, func(err error) error {
return errors.New("mapped error")
})
if mapped.Succeeded() {
t.Errorf("expected Succeeded() to be false")
}
if mapped.PartiallySucceeded() {
t.Errorf("expected PartiallySucceeded() to be false")
}
if !mapped.Failed() {
t.Errorf("expected Failed() to be true")
}
if mapped.HasValue() {
t.Errorf("expected HasValue() to be false")
}
if !mapped.HasError() {
t.Errorf("expected HasError() to be true")
}
if mapped.Error().GetOrZero().Error() != "mapped error" {
t.Errorf("expected Error() to return mapped error")
}
if mapped.Value().Present() {
t.Errorf("expected Value() to be empty")
}
if mapped.String() != "Failure(mapped error)" {
t.Errorf("expected String() to return Failure(mapped error)")
}
})

t.Run("PartialSuccess", func(t *testing.T) {
r := OfPartialSuccess(42, errors.New("error"))
mapped := MapError(r, func(err error) error {
return errors.New("mapped error")
})
if mapped.Succeeded() {
t.Errorf("expected Succeeded() to be false")
}
if !mapped.PartiallySucceeded() {
t.Errorf("expected PartiallySucceeded() to be true")
}
if mapped.Failed() {
t.Errorf("expected Failed() to be false")
}
if !mapped.HasValue() {
t.Errorf("expected HasValue() to be true")
}
if !mapped.HasError() {
t.Errorf("expected HasError() to be true")
}
if mapped.Value().GetOrZero() != 42 {
t.Errorf("expected Value() to return 42")
}
if mapped.Error().GetOrZero().Error() != "mapped error" {
t.Errorf("expected Error() to return mapped error")
}
if mapped.String() != "PartialSuccess(42, mapped error)" {
t.Errorf("expected String() to return PartialSuccess(42, mapped error)")
}
})
}

0 comments on commit 16658ea

Please sign in to comment.