diff --git a/README.md b/README.md index 46be3ee..db75b93 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [![GoDoc](https://godoc.org/github.com/andeya/gust?status.svg)](https://pkg.go.dev/github.com/andeya/gust) ![Build Status](https://github.com/andeya/gust/actions/workflows/go.yml/badge.svg) [![Go report](https://goreportcard.com/badge/github.com/andeya/gust)](https://goreportcard.com/report/github.com/andeya/gust) -[![Coverage](https://img.shields.io/codecov/c/github/samber/do)](https://codecov.io/gh/andeya/gust) +[![Coverage](https://img.shields.io/codecov/c/github/andeya/gust)](https://codecov.io/gh/andeya/gust) [![License](https://img.shields.io/github/license/andeya/gust)](./LICENSE) A Rust-inspired **declarative-programming and generic-type module** for Golang that helps avoid bugs and improve development efficiency. diff --git a/enum_result_test.go b/enum_result_test.go index 600e4be..e736b88 100644 --- a/enum_result_test.go +++ b/enum_result_test.go @@ -65,3 +65,21 @@ func TestEnumResultUnwrapOrThrow_2(t *testing.T) { defer gust.CatchEnumResult[int, string](&r) panic("panic text") } + +func TestEnumResult_Err(t *testing.T) { + { + var x = gust.EnumOk[int, string](2) + assert.Equal(t, gust.None[string](), x.Err()) + } + { + var x = gust.EnumErr[int, string]("some error message") + assert.Equal(t, gust.Some[string]("some error message"), x.Err()) + } +} + +func TestEnumResult_IsErrAnd(t *testing.T) { + { + var x = gust.EnumErr[int, int8](-1) + assert.True(t, x.IsErrAnd(func(x int8) bool { return x == -1 })) + } +} diff --git a/examples/iterator/advance_by_test.go b/examples/iterator/advance_by_test.go deleted file mode 100644 index b465b67..0000000 --- a/examples/iterator/advance_by_test.go +++ /dev/null @@ -1,28 +0,0 @@ -package iterator_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/iter" - "github.com/stretchr/testify/assert" -) - -func TestAdvanceBy(t *testing.T) { - var c = make(chan int, 4) - c <- 1 - c <- 2 - c <- 3 - c <- 4 - close(c) - for _, i := range []iter.Iterator[int]{ - iter.FromElements(1, 2, 3, 4), - iter.FromRange(1, 4, true), - iter.FromChan(c), - } { - assert.Equal(t, gust.NonErrable[uint](), i.AdvanceBy(2)) - assert.Equal(t, gust.Some(3), i.Next()) - assert.Equal(t, gust.NonErrable[uint](), i.AdvanceBy(0)) - assert.Equal(t, gust.ToErrable[uint](1), i.AdvanceBy(100)) // only `4` was skipped - } -} diff --git a/examples/iterator/all_test.go b/examples/iterator/all_test.go deleted file mode 100644 index dec9735..0000000 --- a/examples/iterator/all_test.go +++ /dev/null @@ -1,33 +0,0 @@ -package iterator_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/iter" - "github.com/stretchr/testify/assert" -) - -func TestAll_1(t *testing.T) { - var a = []int8{1, 2, 3} - var all = iter.FromVec[int8](a).All(func(v int8) bool { - return v > 0 - }) - assert.True(t, all) - all = iter.FromVec[int8](a).All(func(v int8) bool { - return v > 2 - }) - assert.False(t, all) -} - -func TestAll_2(t *testing.T) { - var a = []int8{1, 2, 3} - var i = iter.FromVec[int8](a) - var all = i.All(func(v int8) bool { - return v != 2 - }) - assert.False(t, all) - // we can still use `i`, as there are more elements. - var next = i.Next() - assert.Equal(t, gust.Some(int8(3)), next) -} diff --git a/examples/iterator/any_test.go b/examples/iterator/any_test.go deleted file mode 100644 index 3e7fa3f..0000000 --- a/examples/iterator/any_test.go +++ /dev/null @@ -1,33 +0,0 @@ -package iterator_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/iter" - "github.com/stretchr/testify/assert" -) - -func TestAny_1(t *testing.T) { - var a = []int8{1, 2, 3} - var hasAny = iter.FromVec[int8](a).Any(func(v int8) bool { - return v > 0 - }) - assert.True(t, hasAny) - hasAny = iter.FromVec[int8](a).Any(func(v int8) bool { - return v > 5 - }) - assert.False(t, hasAny) -} - -func TestAny_2(t *testing.T) { - var a = []int8{1, 2, 3} - var i = iter.FromVec[int8](a) - var hasAny = i.Any(func(v int8) bool { - return v != 2 - }) - assert.True(t, hasAny) - // we can still use `i`, as there are more elements. - var next = i.Next() - assert.Equal(t, gust.Some(int8(2)), next) -} diff --git a/examples/iterator/chain_test.go b/examples/iterator/chain_test.go deleted file mode 100644 index 8d7d024..0000000 --- a/examples/iterator/chain_test.go +++ /dev/null @@ -1,30 +0,0 @@ -package iterator_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/iter" - "github.com/stretchr/testify/assert" -) - -func TestChain(t *testing.T) { - var c = make(chan int, 3) - c <- 4 - c <- 5 - c <- 6 - close(c) - for _, x := range [][2]iter.Iterator[int]{ - {iter.FromElements(1, 2, 3), iter.FromElements(4, 5, 6)}, - {iter.FromRange(1, 4), iter.FromChan(c)}, - } { - var i = x[0].ToChain(x[1]) - assert.Equal(t, gust.Some(1), i.Next()) - assert.Equal(t, gust.Some(2), i.Next()) - assert.Equal(t, gust.Some(3), i.Next()) - assert.Equal(t, gust.Some(4), i.Next()) - assert.Equal(t, gust.Some(5), i.Next()) - assert.Equal(t, gust.Some(6), i.Next()) - assert.Equal(t, gust.None[int](), i.Next()) - } -} diff --git a/examples/iterator/count_test.go b/examples/iterator/count_test.go deleted file mode 100644 index 50e8082..0000000 --- a/examples/iterator/count_test.go +++ /dev/null @@ -1,27 +0,0 @@ -package iterator_test - -import ( - "testing" - - "github.com/andeya/gust/iter" - "github.com/stretchr/testify/assert" -) - -func TestCount_1(t *testing.T) { - assert.Equal(t, uint(3), iter.FromElements(1, 2, 3).Count()) - assert.Equal(t, uint(5), iter.FromElements(1, 2, 3, 4, 5).Count()) -} - -func TestCount_2(t *testing.T) { - assert.Equal(t, uint(3), iter.FromRange(1, 3, true).Count()) - assert.Equal(t, uint(5), iter.FromRange(1, 6, false).Count()) - assert.Equal(t, uint(5), iter.FromRange(1, 6).Count()) -} - -func TestCount_3(t *testing.T) { - var c = make(chan int, 3) - c <- 1 - c <- 2 - c <- 3 - assert.Equal(t, uint(3), iter.FromChan(c).Count()) -} diff --git a/examples/iterator/enumerate_test.go b/examples/iterator/enumerate_test.go deleted file mode 100644 index 4898be2..0000000 --- a/examples/iterator/enumerate_test.go +++ /dev/null @@ -1,23 +0,0 @@ -package iterator_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/iter" - "github.com/stretchr/testify/assert" -) - -func TestEnumerate(t *testing.T) { - var i = iter.EnumElements[rune]('a', 'b', 'c') - assert.Equal(t, gust.Some(gust.VecEntry[rune]{ - Index: 0, Elem: 'a', - }), i.Next()) - assert.Equal(t, gust.Some(gust.VecEntry[rune]{ - Index: 1, Elem: 'b', - }), i.Next()) - assert.Equal(t, gust.Some(gust.VecEntry[rune]{ - Index: 2, Elem: 'c', - }), i.Next()) - assert.Equal(t, gust.None[gust.VecEntry[rune]](), i.Next()) -} diff --git a/examples/iterator/filter_map_test.go b/examples/iterator/filter_map_test.go deleted file mode 100644 index 56458cc..0000000 --- a/examples/iterator/filter_map_test.go +++ /dev/null @@ -1,44 +0,0 @@ -package iterator_test - -import ( - "strconv" - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/iter" - "github.com/stretchr/testify/assert" -) - -func TestFilterMap_1(t *testing.T) { - var c = make(chan string, 10) - for idx, i := range []iter.Iterator[string]{ - iter.FromElements("1", "two", "NaN", "four", "5"), - iter.FromChan(c), - } { - var i = iter.ToFilterMap[string, int](i.ToInspect(func(v string) { - if idx == 0 { - c <- v - } - }), func(v string) gust.Option[int] { return gust.Ret(strconv.Atoi(v)).Ok() }) - assert.Equal(t, gust.Some[int](1), i.Next()) - assert.Equal(t, gust.Some[int](5), i.Next()) - assert.Equal(t, gust.None[int](), i.Next()) - } -} - -func TestFilterMap_2(t *testing.T) { - var c = make(chan string, 10) - for idx, i := range []iter.Iterator[string]{ - iter.FromElements("1", "two", "NaN", "four", "5"), - iter.FromChan(c), - } { - var i = i.ToInspect(func(v string) { - if idx == 0 { - c <- v - } - }).ToXFilterMap(func(v string) gust.Option[any] { return gust.Ret(strconv.Atoi(v)).Ok().ToX() }) - assert.Equal(t, gust.Some[any](1), i.Next()) - assert.Equal(t, gust.Some[any](5), i.Next()) - assert.Equal(t, gust.None[any](), i.Next()) - } -} diff --git a/examples/iterator/filter_test.go b/examples/iterator/filter_test.go deleted file mode 100644 index 679bcec..0000000 --- a/examples/iterator/filter_test.go +++ /dev/null @@ -1,27 +0,0 @@ -package iterator_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/iter" - "github.com/stretchr/testify/assert" -) - -func TestFilter(t *testing.T) { - var c = make(chan int, 10) - c <- 0 - c <- 1 - c <- 2 - close(c) - for _, i := range []iter.Iterator[int]{ - iter.FromElements(0, 1, 2), - iter.FromRange(0, 3), - iter.FromChan(c), - } { - var i = i.ToFilter(func(v int) bool { return v > 0 }) - assert.Equal(t, gust.Some(1), i.Next()) - assert.Equal(t, gust.Some(2), i.Next()) - assert.Equal(t, gust.None[int](), i.Next()) - } -} diff --git a/examples/iterator/find_map_test.go b/examples/iterator/find_map_test.go deleted file mode 100644 index 0e87662..0000000 --- a/examples/iterator/find_map_test.go +++ /dev/null @@ -1,18 +0,0 @@ -package iterator_test - -import ( - "strconv" - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/iter" - "github.com/stretchr/testify/assert" -) - -func TestFindMap(t *testing.T) { - var firstNumbe = iter.FromElements("lol", "NaN", "2", "5"). - XFindMap(func(s string) gust.Option[any] { - return gust.Ret(strconv.Atoi(s)).XOk() - }) - assert.Equal(t, gust.Some[any](int(2)), firstNumbe) -} diff --git a/examples/iterator/find_test.go b/examples/iterator/find_test.go deleted file mode 100644 index e342bb8..0000000 --- a/examples/iterator/find_test.go +++ /dev/null @@ -1,31 +0,0 @@ -package iterator_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/iter" - "github.com/stretchr/testify/assert" -) - -func TestFind_1(t *testing.T) { - var a = []int8{1, 2, 3} - var i = iter.FromVec[int8](a) - assert.Equal(t, gust.Some[int8](2), i.Find(func(v int8) bool { - return v == 2 - })) - assert.Equal(t, gust.None[int8](), i.Find(func(v int8) bool { - return v == 5 - })) -} - -func TestFind_2(t *testing.T) { - var a = []int8{1, 2, 3} - var i = iter.FromVec[int8](a) - // / assert_eq!(iter.find(|&&x| x == 2), Some(&2)); - assert.Equal(t, gust.Some[int8](2), i.Find(func(v int8) bool { - return v == 2 - })) - // we can still use `iter`, as there are more elements. - assert.Equal(t, gust.Some[int8](3), i.Next()) -} diff --git a/examples/iterator/flat_map_test.go b/examples/iterator/flat_map_test.go deleted file mode 100644 index be76cb4..0000000 --- a/examples/iterator/flat_map_test.go +++ /dev/null @@ -1,23 +0,0 @@ -package iterator_test - -import ( - "testing" - - "github.com/andeya/gust/iter" - "github.com/stretchr/testify/assert" -) - -func TestFlatMap(t *testing.T) { - var c = make(chan string, 10) - for _, i := range []iter.Iterator[string]{ - iter.FromElements("alpha", "beta", "gamma").ToInspect(func(v string) { - c <- v - }), - iter.FromChan(c), - } { - var merged = iter.ToFlatMap(i, func(t string) iter.Iterator[rune] { - return iter.FromString[rune](t) - }).Collect() - assert.Equal(t, "alphabetagamma", string(merged)) - } -} diff --git a/examples/iterator/flatten_test.go b/examples/iterator/flatten_test.go deleted file mode 100644 index 2eecac1..0000000 --- a/examples/iterator/flatten_test.go +++ /dev/null @@ -1,17 +0,0 @@ -package iterator_test - -import ( - "testing" - - "github.com/andeya/gust/iter" - "github.com/stretchr/testify/assert" -) - -func TestFlatten(t *testing.T) { - var i = iter.FromElements( - iter.FromElements([]int{1, 2}, []int{3, 4}), - iter.FromElements([]int{5, 6}, []int{7, 8}), - ) - var d2 = iter.ToDeFlatten[iter.DeIterator[[]int], []int](i).Collect() - assert.Equal(t, [][]int{{1, 2}, {3, 4}, {5, 6}, {7, 8}}, d2) -} diff --git a/examples/iterator/fold_test.go b/examples/iterator/fold_test.go deleted file mode 100644 index 7b449ca..0000000 --- a/examples/iterator/fold_test.go +++ /dev/null @@ -1,61 +0,0 @@ -package iterator_test - -import ( - "fmt" - "testing" - - "github.com/andeya/gust/iter" - "github.com/stretchr/testify/assert" -) - -func TestFold_1(t *testing.T) { - var c = make(chan int8, 10) - for _, i := range []iter.Iterator[int8]{ - iter.FromElements[int8](1, 2, 3).ToInspect(func(v int8) { - c <- v - }), - iter.FromRange[int8](1, 3, true), - iter.FromChan(c), - } { - // the sum of all of the elements of the array - var sum = i.Fold(int8(0), func(acc any, v int8) any { - return acc.(int8) + v - }).(int8) - assert.Equal(t, int8(6), sum) - } -} - -func TestFold_2(t *testing.T) { - var c = make(chan int8, 10) - for _, i := range []iter.Iterator[int8]{ - iter.FromElements[int8](1, 2, 3, 4, 5).ToInspect(func(v int8) { - c <- v - }), - iter.FromRange[int8](1, 5, true), - iter.FromChan(c), - } { - var zero = "0" - var result = i.Fold(zero, func(acc any, v int8) any { - return fmt.Sprintf("(%s + %d)", acc.(string), v) - }).(string) - assert.Equal(t, "(((((0 + 1) + 2) + 3) + 4) + 5)", result) - } -} - -func TestFold_3(t *testing.T) { - var numbers = []int{1, 2, 3, 4, 5} - - // for loop: - var result = 0 - for _, x := range numbers { - result = result + x - } - - // fold: - var result2 = iter.FromVec(numbers).Fold(0, func(acc any, x int) any { - return acc.(int) + x - }).(int) - - // they're the same - assert.Equal(t, result, result2) -} diff --git a/examples/iterator/for_each_test.go b/examples/iterator/for_each_test.go deleted file mode 100644 index d3ddf4c..0000000 --- a/examples/iterator/for_each_test.go +++ /dev/null @@ -1,33 +0,0 @@ -package iterator_test - -import ( - "testing" - - "github.com/andeya/gust/iter" - "github.com/stretchr/testify/assert" -) - -func TestForEach_1(t *testing.T) { - var c = make(chan int, 5) - iter.FromRange(0, 5). - ToMap(func(i int) int { return i*2 + 1 }). - ForEach(func(i int) { - c <- i - }) - var v = iter.FromChan(c).Collect() - assert.Equal(t, []int{1, 3, 5, 7, 9}, v) -} - -func TestForEach_2(t *testing.T) { - var c = make(chan int) - go func() { - iter.FromRange(0, 5). - ToMap(func(i int) int { return i*2 + 1 }). - ForEach(func(i int) { - c <- i - }) - close(c) - }() - var v = iter.FromChan(c).Collect() - assert.Equal(t, []int{1, 3, 5, 7, 9}, v) -} diff --git a/examples/iterator/fuse_test.go b/examples/iterator/fuse_test.go deleted file mode 100644 index ac9dfdf..0000000 --- a/examples/iterator/fuse_test.go +++ /dev/null @@ -1,44 +0,0 @@ -package iterator_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/iter" - "github.com/stretchr/testify/assert" -) - -var _ gust.Iterable[int] = (*Alternate)(nil) - -type Alternate struct { - state int -} - -func (a *Alternate) Next() gust.Option[int] { - var val = a.state - a.state = a.state + 1 - // if it's even, Some(i32), else None - if val%2 == 0 { - return gust.Some(val) - } - return gust.None[int]() -} - -func TestFuse(t *testing.T) { - var a = &Alternate{state: 0} - var i = iter.FromIterable[int](a) - // we can see our iterator going back and forth - assert.Equal(t, gust.Some(0), i.Next()) - assert.Equal(t, gust.None[int](), i.Next()) - assert.Equal(t, gust.Some(2), i.Next()) - assert.Equal(t, gust.None[int](), i.Next()) - // however, once we fuse it... - var j = i.ToFuse() - assert.Equal(t, gust.Some(4), j.Next()) - assert.Equal(t, gust.None[int](), j.Next()) - // it will always return `None` after the first time. - assert.Equal(t, gust.None[int](), j.Next()) - assert.Equal(t, gust.None[int](), j.Next()) - assert.Equal(t, gust.None[int](), j.Next()) - -} diff --git a/examples/iterator/inspect_test.go b/examples/iterator/inspect_test.go deleted file mode 100644 index 9aa7f23..0000000 --- a/examples/iterator/inspect_test.go +++ /dev/null @@ -1,28 +0,0 @@ -package iterator_test - -import ( - "fmt" - "strconv" - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/iter" - "github.com/stretchr/testify/assert" -) - -func TestInspect(t *testing.T) { - var numbers = iter.FromElements[string]("1", "2", "a", "3", "b"). - ToXMap(func(v string) any { - return gust.Ret(strconv.Atoi(v)) - }). - ToInspect(func(v any) { - v.(gust.Result[int]).InspectErr(func(err error) { - fmt.Println("Parsing error:", err) - }) - }). - ToFilterMap(func(v any) gust.Option[any] { - return v.(gust.Result[int]).Ok().ToX() - }). - Collect() - assert.Equal(t, []interface{}{1, 2, 3}, numbers) -} diff --git a/examples/iterator/is_partitioned_test.go b/examples/iterator/is_partitioned_test.go deleted file mode 100644 index e31a2e3..0000000 --- a/examples/iterator/is_partitioned_test.go +++ /dev/null @@ -1,17 +0,0 @@ -package iterator_test - -import ( - "testing" - - "github.com/andeya/gust/iter" - "github.com/stretchr/testify/assert" -) - -func TestIsPartitioned(t *testing.T) { - assert.True(t, iter.FromString[rune]("Iterator").IsPartitioned(func(r rune) bool { - return r >= 'A' && r <= 'Z' - })) - assert.False(t, iter.FromString[rune]("IntoIterator").IsPartitioned(func(r rune) bool { - return r >= 'A' && r <= 'Z' - })) -} diff --git a/examples/iterator/last_test.go b/examples/iterator/last_test.go deleted file mode 100644 index 42b4af6..0000000 --- a/examples/iterator/last_test.go +++ /dev/null @@ -1,36 +0,0 @@ -package iterator_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/iter" - "github.com/stretchr/testify/assert" -) - -func TestLast_1(t *testing.T) { - var a = []int{1, 2, 3} - var i = iter.FromVec(a) - assert.Equal(t, gust.Some(3), i.Last()) - assert.Equal(t, gust.None[int](), i.Last()) - assert.Equal(t, gust.None[int](), i.Next()) -} - -func TestLast_2(t *testing.T) { - var i = iter.FromRange(1, 3, true) - assert.Equal(t, gust.Some(3), i.Last()) - assert.Equal(t, gust.None[int](), i.Last()) - assert.Equal(t, gust.None[int](), i.Next()) -} - -func TestLast_3(t *testing.T) { - var c = make(chan int, 3) - c <- 1 - c <- 2 - c <- 3 - close(c) - var i = iter.FromChan(c) - assert.Equal(t, gust.Some(3), i.Last()) - assert.Equal(t, gust.None[int](), i.Last()) - assert.Equal(t, gust.None[int](), i.Next()) -} diff --git a/examples/iterator/lntersperse_test.go b/examples/iterator/lntersperse_test.go deleted file mode 100644 index dc39630..0000000 --- a/examples/iterator/lntersperse_test.go +++ /dev/null @@ -1,73 +0,0 @@ -package iterator_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/iter" - "github.com/stretchr/testify/assert" -) - -func TestIntersperse_1(t *testing.T) { - var c = make(chan int, 4) - c <- 0 - c <- 1 - c <- 2 - close(c) - for _, i := range []iter.Iterator[int]{ - iter.FromElements(0, 1, 2), - iter.FromRange(0, 3), - iter.FromChan(c), - } { - i := i.ToIntersperse(100) - assert.Equal(t, gust.Some(0), i.Next()) // The first element from `a`. - assert.Equal(t, gust.Some(100), i.Next()) // The separator. - assert.Equal(t, gust.Some(1), i.Next()) // The next element from `a`. - assert.Equal(t, gust.Some(100), i.Next()) // The separator. - assert.Equal(t, gust.Some(2), i.Next()) // The last element from `a`. - assert.Equal(t, gust.None[int](), i.Next()) // The iterator is finished. - - } -} - -func TestIntersperse_2(t *testing.T) { - var c = make(chan int, 4) - c <- 0 - c <- 1 - c <- 2 - close(c) - for _, i := range []iter.Iterator[int]{ - iter.FromElements(0, 1, 2), - iter.FromRange(0, 3), - iter.FromChan(c), - } { - i := i.ToPeekable().ToIntersperse(100) - assert.Equal(t, gust.Some(0), i.Next()) // The first element from `a`. - assert.Equal(t, gust.Some(100), i.Next()) // The separator. - assert.Equal(t, gust.Some(1), i.Next()) // The next element from `a`. - assert.Equal(t, gust.Some(100), i.Next()) // The separator. - assert.Equal(t, gust.Some(2), i.Next()) // The last element from `a`. - assert.Equal(t, gust.None[int](), i.Next()) // The iterator is finished. - } -} - -func TestIntersperse_3(t *testing.T) { - var c = make(chan int, 4) - c <- 0 - c <- 1 - c <- 2 - close(c) - for _, i := range []iter.Iterator[int]{ - iter.FromElements(0, 1, 2), - iter.FromRange(0, 3), - iter.FromChan(c), - } { - i := i.ToIntersperseWith(func() int { return 100 }) - assert.Equal(t, gust.Some(0), i.Next()) // The first element from `a`. - assert.Equal(t, gust.Some(100), i.Next()) // The separator. - assert.Equal(t, gust.Some(1), i.Next()) // The next element from `a`. - assert.Equal(t, gust.Some(100), i.Next()) // The separator. - assert.Equal(t, gust.Some(2), i.Next()) // The last element from `a`. - assert.Equal(t, gust.None[int](), i.Next()) // The iterator is finished. - } -} diff --git a/examples/iterator/map_test.go b/examples/iterator/map_test.go deleted file mode 100644 index c41c281..0000000 --- a/examples/iterator/map_test.go +++ /dev/null @@ -1,67 +0,0 @@ -package iterator_test - -import ( - "fmt" - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/iter" - "github.com/stretchr/testify/assert" -) - -func TestMap_1(t *testing.T) { - var c = make(chan int, 4) - c <- 1 - c <- 2 - c <- 3 - close(c) - for _, i := range []iter.Iterator[int]{ - iter.FromElements(1, 2, 3), - iter.FromRange(1, 4), - iter.FromChan(c), - } { - i := i.ToMap(func(v int) int { return v * 2 }) - assert.Equal(t, gust.Some(2), i.Next()) - assert.Equal(t, gust.Some(4), i.Next()) - assert.Equal(t, gust.Some(6), i.Next()) - assert.Equal(t, gust.None[int](), i.Next()) - } -} - -func TestMap_2(t *testing.T) { - var c = make(chan int, 4) - c <- 1 - c <- 2 - c <- 3 - close(c) - for _, i := range []iter.Iterator[int]{ - iter.FromElements(1, 2, 3), - iter.FromRange(1, 4), - iter.FromChan(c), - } { - i := i.ToXMap(func(v int) any { return fmt.Sprintf("%d", v*2) }) - assert.Equal(t, gust.Some[any]("2"), i.Next()) - assert.Equal(t, gust.Some[any]("4"), i.Next()) - assert.Equal(t, gust.Some[any]("6"), i.Next()) - assert.Equal(t, gust.None[any](), i.Next()) - } -} - -func TestMap_3(t *testing.T) { - var c = make(chan int, 4) - c <- 1 - c <- 2 - c <- 3 - close(c) - for _, i := range []iter.Iterator[int]{ - iter.FromElements(1, 2, 3), - iter.FromRange(1, 4), - iter.FromChan(c), - } { - i := iter.ToMap(i, func(v int) string { return fmt.Sprintf("%d", v*2) }) - assert.Equal(t, gust.Some[string]("2"), i.Next()) - assert.Equal(t, gust.Some[string]("4"), i.Next()) - assert.Equal(t, gust.Some[string]("6"), i.Next()) - assert.Equal(t, gust.None[string](), i.Next()) - } -} diff --git a/examples/iterator/map_while_test.go b/examples/iterator/map_while_test.go deleted file mode 100644 index 3064e1f..0000000 --- a/examples/iterator/map_while_test.go +++ /dev/null @@ -1,50 +0,0 @@ -package iterator_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/iter" - "github.com/stretchr/testify/assert" -) - -func TestMapWhile_1(t *testing.T) { - var c = make(chan int, 10) - for _, i := range []iter.Iterator[int]{ - iter.FromElements(-1, 4, 0, 1).ToInspect(func(v int) { - c <- v - }), - iter.FromChan(c), - } { - i := i.ToMapWhile(func(x int) gust.Option[int] { return checkedDivide(16, x) }) - assert.Equal(t, gust.Some(-16), i.Next()) - assert.Equal(t, gust.Some(4), i.Next()) - assert.Equal(t, gust.None[int](), i.Next()) - assert.Equal(t, gust.Some(16), i.Next()) - } -} - -func checkedDivide(x, y int) gust.Option[int] { - if y == 0 { - return gust.None[int]() - } - return gust.Some(x / y) -} - -func TestMapWhile_2(t *testing.T) { - var c = make(chan int, 10) - for _, i := range []iter.Iterator[int]{ - iter.FromElements(1, 2, -3, 4).ToInspect(func(v int) { - c <- v - }), - iter.FromChan(c), - } { - a := i.ToXMapWhile(func(x int) gust.Option[any] { - if x < 0 { - return gust.None[any]() - } - return gust.Some[any](uint(x)) - }).Collect() - assert.Equal(t, []any{uint(1), uint(2)}, a) - } -} diff --git a/examples/iterator/next_chunk_test.go b/examples/iterator/next_chunk_test.go deleted file mode 100644 index 9074366..0000000 --- a/examples/iterator/next_chunk_test.go +++ /dev/null @@ -1,28 +0,0 @@ -package iterator_test - -import ( - "testing" - - "github.com/andeya/gust/iter" - "github.com/stretchr/testify/assert" -) - -func TestNextChunk_1(t *testing.T) { - var i = iter.FromString[rune]("中国-CN") - assert.Equal(t, []rune{'中', '国'}, i.NextChunk(2).Unwrap()) - assert.Equal(t, []rune{'-', 'C'}, i.NextChunk(2).Unwrap()) - assert.Equal(t, []rune{'N'}, i.NextChunk(4).UnwrapErr()) - assert.Equal(t, []rune{}, i.NextChunk(1).UnwrapErr()) - assert.Equal(t, []rune{}, i.NextChunk(0).Unwrap()) -} - -func TestNextChunk_2(t *testing.T) { - var i = iter.FromString[byte]("中国-CN") - assert.Equal(t, []byte{0xe4, 0xb8, 0xad}, i.NextChunk(3).Unwrap()) // '中' - assert.Equal(t, []byte{0xe5, 0x9b, 0xbd}, i.NextChunk(3).Unwrap()) // '国' - assert.Equal(t, []byte{'-'}, i.NextChunk(1).Unwrap()) - assert.Equal(t, []byte{'C'}, i.NextChunk(1).Unwrap()) - assert.Equal(t, []byte{'N'}, i.NextChunk(3).UnwrapErr()) - assert.Equal(t, []byte{}, i.NextChunk(1).UnwrapErr()) - assert.Equal(t, []byte{}, i.NextChunk(0).Unwrap()) -} diff --git a/examples/iterator/next_test.go b/examples/iterator/next_test.go deleted file mode 100644 index 6adc269..0000000 --- a/examples/iterator/next_test.go +++ /dev/null @@ -1,54 +0,0 @@ -package iterator_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/iter" - "github.com/stretchr/testify/assert" -) - -func TestNext_1(t *testing.T) { - var a = []int{1, 2, 3} - var i = iter.FromVec(a) - // A call to Next() returns the next value... - assert.Equal(t, gust.Some(1), i.Next()) - assert.Equal(t, gust.Some(2), i.Next()) - assert.Equal(t, gust.Some(3), i.Next()) - // ... and then None once it's over. - assert.Equal(t, gust.None[int](), i.Next()) - // More calls may or may not return `None`. Here, they always will. - assert.Equal(t, gust.None[int](), i.Next()) - assert.Equal(t, gust.None[int](), i.Next()) -} - -func TestNext_2(t *testing.T) { - var i = iter.FromRange(1, 3, true) - // A call to Next() returns the next value... - assert.Equal(t, gust.Some(1), i.Next()) - assert.Equal(t, gust.Some(2), i.Next()) - assert.Equal(t, gust.Some(3), i.Next()) - // ... and then None once it's over. - assert.Equal(t, gust.None[int](), i.Next()) - // More calls may or may not return `None`. Here, they always will. - assert.Equal(t, gust.None[int](), i.Next()) - assert.Equal(t, gust.None[int](), i.Next()) -} - -func TestNext_3(t *testing.T) { - var c = make(chan int, 3) - c <- 1 - c <- 2 - c <- 3 - close(c) - var i = iter.FromChan(c) - // A call to Next() returns the next value... - assert.Equal(t, gust.Some(1), i.Next()) - assert.Equal(t, gust.Some(2), i.Next()) - assert.Equal(t, gust.Some(3), i.Next()) - // ... and then None once it's over. - assert.Equal(t, gust.None[int](), i.Next()) - // More calls may or may not return `None`. Here, they always will. - assert.Equal(t, gust.None[int](), i.Next()) - assert.Equal(t, gust.None[int](), i.Next()) -} diff --git a/examples/iterator/nth_test.go b/examples/iterator/nth_test.go deleted file mode 100644 index 3772e90..0000000 --- a/examples/iterator/nth_test.go +++ /dev/null @@ -1,28 +0,0 @@ -package iterator_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/iter" - "github.com/stretchr/testify/assert" -) - -func TestNth(t *testing.T) { - var c = make(chan int, 4) - c <- 1 - c <- 2 - c <- 3 - close(c) - for _, i := range []iter.Iterator[int]{ - iter.FromElements(1, 2, 3), - iter.FromRange(1, 4), - iter.FromChan(c), - } { - assert.Equal(t, gust.Some(2), i.Nth(1)) - // Calling `Nth()` multiple times doesn't rewind the iterator: - assert.Equal(t, gust.None[int](), i.Nth(1)) - // Returning `None` if there are less than `n + 1` elements: - assert.Equal(t, gust.None[int](), i.Nth(10)) - } -} diff --git a/examples/iterator/partition_test.go b/examples/iterator/partition_test.go deleted file mode 100644 index 009e981..0000000 --- a/examples/iterator/partition_test.go +++ /dev/null @@ -1,23 +0,0 @@ -package iterator_test - -import ( - "testing" - - "github.com/andeya/gust/iter" - "github.com/stretchr/testify/assert" -) - -func TestPartition(t *testing.T) { - var c = make(chan int, 10) - for _, i := range []iter.Iterator[int]{ - iter.FromElements(1, 2, 3).ToInspect(func(v int) { - c <- v - }), - iter.FromRange(1, 4), - iter.FromChan(c), - } { - var even, odd = i.Partition(func(x int) bool { return x%2 == 0 }) - assert.Equal(t, []int{2}, even) - assert.Equal(t, []int{1, 3}, odd) - } -} diff --git a/examples/iterator/peekable_test.go b/examples/iterator/peekable_test.go deleted file mode 100644 index fe59954..0000000 --- a/examples/iterator/peekable_test.go +++ /dev/null @@ -1,24 +0,0 @@ -package iterator_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/iter" - "github.com/stretchr/testify/assert" -) - -func TestPeekable(t *testing.T) { - var i = iter.FromElements(1, 2, 3).ToPeekable() - assert.Equal(t, gust.Some(1), i.Peek()) - assert.Equal(t, gust.Some(1), i.Peek()) - assert.Equal(t, gust.Some(1), i.Next()) - peeked := i.Peek() - if peeked.IsSome() { - p := peeked.GetOrInsertWith(nil) - assert.Equal(t, 2, *p) - *p = 1000 - } - // The value reappears as the iterator continues - assert.Equal(t, []int{1000, 3}, i.Collect()) -} diff --git a/examples/iterator/position_test.go b/examples/iterator/position_test.go deleted file mode 100644 index 9fc8dbd..0000000 --- a/examples/iterator/position_test.go +++ /dev/null @@ -1,33 +0,0 @@ -package iterator_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/iter" - "github.com/stretchr/testify/assert" -) - -func TestPosition_1(t *testing.T) { - var a = []int8{1, 2, 3} - assert.Equal(t, gust.Some(1), iter.FromVec[int8](a).Position(func(v int8) bool { - return v == 2 - })) - assert.Equal(t, gust.None[int](), iter.FromVec[int8](a).Position(func(v int8) bool { - return v == 5 - })) -} - -func TestPosition_2(t *testing.T) { - // Stopping at the first `true`: - var a = iter.FromElements(1, 2, 3, 4) - assert.Equal(t, gust.Some(1), a.Position(func(v int) bool { - return v >= 2 - })) - // we can still use `iter`, as there are more elements. - assert.Equal(t, gust.Some(3), a.Next()) - // The returned index depends on iterator state - assert.Equal(t, gust.Some(0), a.Position(func(v int) bool { - return v == 4 - })) -} diff --git a/examples/iterator/reduce_test.go b/examples/iterator/reduce_test.go deleted file mode 100644 index d0da056..0000000 --- a/examples/iterator/reduce_test.go +++ /dev/null @@ -1,25 +0,0 @@ -package iterator_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/iter" - "github.com/stretchr/testify/assert" -) - -func findMax[T gust.Integer](i iter.Iterator[T]) gust.Option[T] { - return i.Reduce(func(acc T, v T) T { - if acc >= v { - return acc - } - return v - }) -} - -func TestReduce(t *testing.T) { - var a = []int{10, 20, 5, -23, 0} - var b []uint - assert.Equal(t, gust.Some(20), findMax[int](iter.FromVec(a))) - assert.Equal(t, gust.None[uint](), findMax[uint](iter.FromVec(b))) -} diff --git a/examples/iterator/rev_test.go b/examples/iterator/rev_test.go deleted file mode 100644 index 6ba7889..0000000 --- a/examples/iterator/rev_test.go +++ /dev/null @@ -1,22 +0,0 @@ -package iterator_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/iter" - "github.com/stretchr/testify/assert" -) - -func TestRev(t *testing.T) { - for _, i := range []iter.DeIterator[int]{ - iter.FromElements(1, 2, 3), - iter.FromRange(1, 3, true), - } { - var rev = i.ToRev() - assert.Equal(t, gust.Some(3), rev.Next()) - assert.Equal(t, gust.Some(2), rev.Next()) - assert.Equal(t, gust.Some(1), rev.Next()) - assert.Equal(t, gust.None[int](), rev.Next()) - } -} diff --git a/examples/iterator/rposition_test.go b/examples/iterator/rposition_test.go deleted file mode 100644 index fd62021..0000000 --- a/examples/iterator/rposition_test.go +++ /dev/null @@ -1,27 +0,0 @@ -package iterator_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/iter" - "github.com/stretchr/testify/assert" -) - -func TestRposition_1(t *testing.T) { - var a = []int8{1, 2, 3} - assert.Equal(t, gust.Some(2), iter.FromVec[int8](a).Rposition(func(v int8) bool { - return v == 3 - })) - assert.Equal(t, gust.None[int](), iter.FromVec[int8](a).Rposition(func(v int8) bool { - return v == 5 - })) -} - -func TestRposition_2(t *testing.T) { - var a = iter.FromElements(1, 2, 3) - assert.Equal(t, gust.Some(1), a.Rposition(func(v int) bool { - return v == 2 - })) - assert.Equal(t, gust.Some(1), a.Next()) -} diff --git a/examples/iterator/scan_test.go b/examples/iterator/scan_test.go deleted file mode 100644 index 854f935..0000000 --- a/examples/iterator/scan_test.go +++ /dev/null @@ -1,31 +0,0 @@ -package iterator_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/iter" - "github.com/stretchr/testify/assert" -) - -func TestScan(t *testing.T) { - var c = make(chan int, 10) - for _, i := range []iter.Iterator[int]{ - iter.FromElements(1, 2, 3).ToInspect(func(v int) { - c <- v - }), - iter.FromRange(1, 4), - iter.FromChan(c), - } { - j := i.ToScan(1, func(state *any, x int) gust.Option[any] { - // each iteration, we'll multiply the state by the element - *state = (*state).(int) * x - // then, we'll yield the negation of the state - return gust.Some[any](-(*state).(int)) - }) - assert.Equal(t, gust.Some[any](-1), j.Next()) - assert.Equal(t, gust.Some[any](-2), j.Next()) - assert.Equal(t, gust.Some[any](-6), j.Next()) - assert.Equal(t, gust.None[any](), j.Next()) - } -} diff --git a/examples/iterator/size_hint_test.go b/examples/iterator/size_hint_test.go deleted file mode 100644 index 0adc32f..0000000 --- a/examples/iterator/size_hint_test.go +++ /dev/null @@ -1,46 +0,0 @@ -package iterator_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/iter" - "github.com/stretchr/testify/assert" -) - -func TestSizeHint_1(t *testing.T) { - var i = iter.FromElements(1, 2, 3) - var lo, hi = i.SizeHint() - assert.Equal(t, uint(3), lo) - assert.Equal(t, gust.Some[uint](3), hi) - _ = i.Next() - lo, hi = i.SizeHint() - assert.Equal(t, uint(2), lo) - assert.Equal(t, gust.Some[uint](2), hi) -} - -func TestSizeHint_2(t *testing.T) { - var i = iter.FromRange(1, 3, true) - var lo, hi = i.SizeHint() - assert.Equal(t, uint(3), lo) - assert.Equal(t, gust.Some[uint](3), hi) - _ = i.Next() - lo, hi = i.SizeHint() - assert.Equal(t, uint(2), lo) - assert.Equal(t, gust.Some[uint](2), hi) -} - -func TestSizeHint_3(t *testing.T) { - var c = make(chan int, 3) - c <- 1 - c <- 2 - c <- 3 - var i = iter.FromChan(c) - var lo, hi = i.SizeHint() - assert.Equal(t, uint(3), lo) - assert.Equal(t, gust.Some[uint](3), hi) - _ = i.Next() - lo, hi = i.SizeHint() - assert.Equal(t, uint(2), lo) - assert.Equal(t, gust.Some[uint](3), hi) -} diff --git a/examples/iterator/skip_test.go b/examples/iterator/skip_test.go deleted file mode 100644 index e39939c..0000000 --- a/examples/iterator/skip_test.go +++ /dev/null @@ -1,24 +0,0 @@ -package iterator_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/iter" - "github.com/stretchr/testify/assert" -) - -func TestSkip(t *testing.T) { - var c = make(chan int, 10) - for _, i := range []iter.Iterator[int]{ - iter.FromElements(1, 2, 3).ToInspect(func(v int) { - c <- v - }), - iter.FromRange(1, 4), - iter.FromChan(c), - } { - var iter = i.ToSkip(2) - assert.Equal(t, gust.Some(3), iter.Next()) - assert.Equal(t, gust.None[int](), iter.Next()) - } -} diff --git a/examples/iterator/skip_while_test.go b/examples/iterator/skip_while_test.go deleted file mode 100644 index bc5c6bb..0000000 --- a/examples/iterator/skip_while_test.go +++ /dev/null @@ -1,28 +0,0 @@ -package iterator_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/iter" - "github.com/stretchr/testify/assert" -) - -func TestSkipWhile(t *testing.T) { - var c = make(chan int, 10) - for _, i := range []iter.Iterator[int]{ - iter.FromElements(-1, 0, 1).ToInspect(func(v int) { - c <- v - }), - iter.FromRange(-1, 2), - iter.FromChan(c), - } { - var iter = i.ToSkipWhile(func(v int) bool { - return v < 0 - }) - assert.Equal(t, gust.Some(0), iter.Next()) - assert.Equal(t, gust.Some(1), iter.Next()) - assert.Equal(t, gust.None[int](), iter.Next()) - } - -} diff --git a/examples/iterator/step_by_test.go b/examples/iterator/step_by_test.go deleted file mode 100644 index 7e00519..0000000 --- a/examples/iterator/step_by_test.go +++ /dev/null @@ -1,31 +0,0 @@ -package iterator_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/iter" - "github.com/stretchr/testify/assert" -) - -func TestStepBy(t *testing.T) { - var c = make(chan int, 6) - c <- 0 - c <- 1 - c <- 2 - c <- 3 - c <- 4 - c <- 5 - close(c) - for _, i := range []iter.Iterator[int]{ - iter.FromElements(0, 1, 2, 3, 4, 5), - iter.FromRange(0, 5, true), - iter.FromChan(c), - } { - var stepBy = i.ToStepBy(2) - assert.Equal(t, gust.Some(0), stepBy.Next()) - assert.Equal(t, gust.Some(2), stepBy.Next()) - assert.Equal(t, gust.Some(4), stepBy.Next()) - assert.Equal(t, gust.None[int](), stepBy.Next()) - } -} diff --git a/examples/iterator/take_test.go b/examples/iterator/take_test.go deleted file mode 100644 index 0197f53..0000000 --- a/examples/iterator/take_test.go +++ /dev/null @@ -1,25 +0,0 @@ -package iterator_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/iter" - "github.com/stretchr/testify/assert" -) - -func TestTake(t *testing.T) { - var c = make(chan int, 10) - for _, i := range []iter.Iterator[int]{ - iter.FromElements(1, 2, 3).ToInspect(func(v int) { - c <- v - }), - iter.FromRange(1, 4), - iter.FromChan(c), - } { - var iter = i.ToTake(2) - assert.Equal(t, gust.Some(1), iter.Next()) - assert.Equal(t, gust.Some(2), iter.Next()) - assert.Equal(t, gust.None[int](), iter.Next()) - } -} diff --git a/examples/iterator/take_while_test.go b/examples/iterator/take_while_test.go deleted file mode 100644 index cb273fc..0000000 --- a/examples/iterator/take_while_test.go +++ /dev/null @@ -1,26 +0,0 @@ -package iterator_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/iter" - "github.com/stretchr/testify/assert" -) - -func TestTakeWhile(t *testing.T) { - var c = make(chan int, 10) - for _, i := range []iter.Iterator[int]{ - iter.FromElements(-1, 0, 1).ToInspect(func(v int) { - c <- v - }), - iter.FromRange(-1, 2), - iter.FromChan(c), - } { - var iter = i.ToTakeWhile(func(v int) bool { - return v < 0 - }) - assert.Equal(t, gust.Some(-1), iter.Next()) - assert.Equal(t, gust.None[int](), iter.Next()) - } -} diff --git a/examples/iterator/try_find_test.go b/examples/iterator/try_find_test.go deleted file mode 100644 index 060e209..0000000 --- a/examples/iterator/try_find_test.go +++ /dev/null @@ -1,28 +0,0 @@ -package iterator_test - -import ( - "strconv" - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/iter" - "github.com/andeya/gust/ret" - "github.com/stretchr/testify/assert" -) - -func TestTryFind(t *testing.T) { - var a = []string{"1", "2", "lol", "NaN", "5"} - var isMyNum = func(s string, search int) gust.Result[bool] { - return ret.Map[int, bool](gust.Ret(strconv.Atoi(s)), func(x int) bool { - return x == search - }) - } - var result = iter.FromVec[string](a).TryFind(func(s string) gust.Result[bool] { - return isMyNum(s, 2) - }) - assert.Equal(t, gust.Ok(gust.Some[string]("2")), result) - result = iter.FromVec[string](a).TryFind(func(s string) gust.Result[bool] { - return isMyNum(s, 5) - }) - assert.True(t, result.IsErr()) -} diff --git a/examples/iterator/try_fold_test.go b/examples/iterator/try_fold_test.go deleted file mode 100644 index a84c663..0000000 --- a/examples/iterator/try_fold_test.go +++ /dev/null @@ -1,62 +0,0 @@ -package iterator_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/digit" - "github.com/andeya/gust/iter" - "github.com/stretchr/testify/assert" -) - -func TestTryFold_1(t *testing.T) { - var c = make(chan int8, 10) - for _, i := range []iter.Iterator[int8]{ - iter.FromElements[int8](1, 2, 3).ToInspect(func(v int8) { - c <- v - }), - iter.FromRange[int8](1, 4), - iter.FromChan(c), - } { - // the checked sum of all the elements of the array - var sum = i.TryFold(int8(0), func(acc any, v int8) gust.AnyCtrlFlow { - return digit.CheckedAdd[int8](acc.(int8), v).CtrlFlow().ToX() - }) - assert.Equal(t, gust.AnyContinue(int8(6)), sum) - } -} - -func TestTryFold_2(t *testing.T) { - var i = iter.FromElements[int8](10, 20, 30, 100, 40, 50) - // This sum overflows when adding the 100 element - var sum = i.TryFold(int8(0), func(acc any, v int8) gust.AnyCtrlFlow { - return digit.CheckedAdd[int8](acc.(int8), v).CtrlFlow().ToX() - }) - assert.Equal(t, gust.AnyBreak(gust.Void(nil)), sum) - // Because it short-circuited, the remaining elements are still - // available through the iterator. - assert.Equal(t, uint(2), i.Remaining()) - assert.Equal(t, gust.Some[int8](40), i.Next()) -} - -func TestTryFold_3(t *testing.T) { - var triangular8 = iter.FromRange[int8](1, 30).TryFold(int8(0), func(acc any, v int8) gust.AnyCtrlFlow { - return digit.CheckedAdd[int8](acc.(int8), v).XMapOrElse( - func() any { - return gust.AnyBreak(acc) - }, func(sum int8) any { - return gust.AnyContinue(sum) - }).(gust.AnyCtrlFlow) - }) - assert.Equal(t, gust.AnyBreak(int8(120)), triangular8) - - var triangular64 = iter.FromRange[uint64](1, 30).TryFold(uint64(0), func(acc any, v uint64) gust.AnyCtrlFlow { - return digit.CheckedAdd(acc.(uint64), v).XMapOrElse( - func() any { - return gust.AnyBreak(acc) - }, func(sum uint64) any { - return gust.AnyContinue(sum) - }).(gust.AnyCtrlFlow) - }) - assert.Equal(t, gust.AnyContinue(uint64(435)), triangular64) -} diff --git a/examples/iterator/try_for_each_test.go b/examples/iterator/try_for_each_test.go deleted file mode 100644 index d9e330b..0000000 --- a/examples/iterator/try_for_each_test.go +++ /dev/null @@ -1,27 +0,0 @@ -package iterator_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/iter" - "github.com/stretchr/testify/assert" -) - -func TestTryForEach(t *testing.T) { - var c = make(chan int, 1000) - for _, i := range []iter.Iterator[int]{ - iter.FromRange[int](2, 100).ToInspect(func(v int) { - c <- v - }), - iter.FromChan(c), - } { - var r = i.TryForEach(func(v int) gust.AnyCtrlFlow { - if 323%v == 0 { - return gust.AnyBreak(v) - } - return gust.AnyContinue(nil) - }) - assert.Equal(t, gust.AnyBreak(17), r) - } -} diff --git a/examples/iterator/try_reduce_test.go b/examples/iterator/try_reduce_test.go deleted file mode 100644 index 1b0e39d..0000000 --- a/examples/iterator/try_reduce_test.go +++ /dev/null @@ -1,37 +0,0 @@ -package iterator_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/digit" - "github.com/andeya/gust/iter" - "github.com/stretchr/testify/assert" -) - -func TestTryReduce_1(t *testing.T) { - // Safely calculate the sum of a series of numbers: - var numbers = []uint{10, 20, 5, 23, 0} - var sum = iter.FromVec(numbers).TryReduce(func(x, y uint) gust.Result[uint] { - return digit.CheckedAdd(x, y).OkOr("overflow") - }) - assert.Equal(t, gust.Ok(gust.Some[uint](58)), sum) -} - -func TestTryReduce_2(t *testing.T) { - // Determine when a reduction short circuited: - var numbers = []uint{1, 2, 3, ^uint(0), 4, 5} - var sum = iter.FromVec(numbers).TryReduce(func(x, y uint) gust.Result[uint] { - return digit.CheckedAdd(x, y).OkOr("overflow") - }) - assert.Equal(t, gust.Err[gust.Option[uint]]("overflow"), sum) -} - -func TestTryReduce_3(t *testing.T) { - // Determine when a reduction was not performed because there are no elements: - var numbers = []uint{} - var sum = iter.FromVec(numbers).TryReduce(func(x, y uint) gust.Result[uint] { - return digit.CheckedAdd(x, y).OkOr("overflow") - }) - assert.Equal(t, gust.Ok(gust.None[uint]()), sum) -} diff --git a/examples/iterator/zip_test.go b/examples/iterator/zip_test.go deleted file mode 100644 index f61f5e0..0000000 --- a/examples/iterator/zip_test.go +++ /dev/null @@ -1,27 +0,0 @@ -package iterator_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/iter" - "github.com/stretchr/testify/assert" -) - -func TestZip(t *testing.T) { - var c = make(chan int, 3) - c <- 4 - c <- 5 - c <- 6 - close(c) - for _, x := range [][2]iter.Iterator[int]{ - {iter.FromElements(1, 2, 3), iter.FromElements(4, 5, 6)}, - {iter.FromRange(1, 4), iter.FromChan(c)}, - } { - var i = iter.ToZip(x[0], x[1]) - assert.Equal(t, gust.Some(gust.Pair[int, int]{A: 1, B: 4}), i.Next()) - assert.Equal(t, gust.Some(gust.Pair[int, int]{A: 2, B: 5}), i.Next()) - assert.Equal(t, gust.Some(gust.Pair[int, int]{A: 3, B: 6}), i.Next()) - assert.Equal(t, gust.None[gust.Pair[int, int]](), i.Next()) - } -} diff --git a/examples/option/and_test.go b/examples/option/and_test.go deleted file mode 100644 index d67ee84..0000000 --- a/examples/option/and_test.go +++ /dev/null @@ -1,54 +0,0 @@ -package option_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/stretchr/testify/assert" -) - -func TestOption_And_1(t *testing.T) { - { - var x = gust.Some[uint32](2) - var y gust.Option[uint32] - assert.Equal(t, gust.None[uint32](), x.And(y)) - } - { - var x gust.Option[uint32] - var y = gust.Some[uint32](3) - assert.Equal(t, gust.None[uint32](), x.And(y)) - } - { - var x = gust.Some[uint32](2) - var y = gust.Some[uint32](3) - assert.Equal(t, gust.Some[uint32](3), x.And(y)) - } - { - var x gust.Option[uint32] - var y gust.Option[uint32] - assert.Equal(t, gust.None[uint32](), x.And(y)) - } -} - -func TestOption_And_2(t *testing.T) { - { - var x = gust.Some[uint32](2) - var y gust.Option[string] - assert.Equal(t, gust.None[string]().ToX(), x.XAnd(y.ToX())) - } - { - var x gust.Option[uint32] - var y = gust.Some[string]("foo") - assert.Equal(t, gust.None[string]().ToX(), x.XAnd(y.ToX())) - } - { - var x = gust.Some[uint32](2) - var y = gust.Some[string]("foo") - assert.Equal(t, gust.Some[string]("foo").ToX(), x.XAnd(y.ToX())) - } - { - var x gust.Option[uint32] - var y gust.Option[string] - assert.Equal(t, gust.None[string]().ToX(), x.XAnd(y.ToX())) - } -} diff --git a/examples/option/and_then_test.go b/examples/option/and_then_test.go deleted file mode 100644 index 1da4020..0000000 --- a/examples/option/and_then_test.go +++ /dev/null @@ -1,35 +0,0 @@ -package option_test - -import ( - "math" - "strconv" - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/opt" - "github.com/stretchr/testify/assert" -) - -func TestOption_AndThen_1(t *testing.T) { - var sqThenToString = func(x uint32) gust.Option[string] { - if x <= math.MaxUint32/x { - return gust.Some(strconv.FormatUint(uint64(x*x), 10)) - } - return gust.None[string]() - } - assert.Equal(t, gust.Some("4"), opt.AndThen(gust.Some[uint32](2), sqThenToString)) - assert.Equal(t, gust.None[string](), opt.AndThen(gust.Some[uint32](1000000), sqThenToString)) - assert.Equal(t, gust.None[string](), opt.AndThen(gust.None[uint32](), sqThenToString)) -} - -func TestOption_AndThen_2(t *testing.T) { - var sqThenToString = func(x uint32) gust.Option[any] { - if x <= math.MaxUint32/x { - return gust.Some[any](strconv.FormatUint(uint64(x*x), 10)) - } - return gust.None[any]() - } - assert.Equal(t, gust.Some("4").ToX(), gust.Some[uint32](2).XAndThen(sqThenToString)) - assert.Equal(t, gust.None[string]().ToX(), gust.Some[uint32](1000000).XAndThen(sqThenToString)) - assert.Equal(t, gust.None[string]().ToX(), gust.None[uint32]().XAndThen(sqThenToString)) -} diff --git a/examples/option/contains_test.go b/examples/option/contains_test.go deleted file mode 100644 index a0feec8..0000000 --- a/examples/option/contains_test.go +++ /dev/null @@ -1,24 +0,0 @@ -package option_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/opt" - "github.com/stretchr/testify/assert" -) - -func TestOption_Contains(t *testing.T) { - { - var x = gust.Some(2) - assert.Equal(t, true, opt.Contains(x, 2)) - } - { - var x = gust.Some(3) - assert.Equal(t, false, opt.Contains(x, 2)) - } - { - var x = gust.None[int]() - assert.Equal(t, false, opt.Contains(x, 2)) - } -} diff --git a/examples/option/expect_test.go b/examples/option/expect_test.go deleted file mode 100644 index c87453c..0000000 --- a/examples/option/expect_test.go +++ /dev/null @@ -1,25 +0,0 @@ -package option_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/stretchr/testify/assert" -) - -func TestOption_Expect(t *testing.T) { - { - var x = gust.Some("value") - assert.Equal(t, "value", x.Expect("fruits are healthy")) - } - defer func() { - assert.Equal(t, gust.ToErrBox("fruits are healthy 1"), recover()) - defer func() { - assert.Equal(t, gust.ToErrBox("fruits are healthy 2"), recover()) - }() - var x gust.Option[string] - x.Expect("fruits are healthy 2") // panics with `fruits are healthy 2` - }() - var x = gust.None[string]() - x.Expect("fruits are healthy 1") // panics with `fruits are healthy 1` -} diff --git a/examples/option/filter_test.go b/examples/option/filter_test.go deleted file mode 100644 index 83a0cd6..0000000 --- a/examples/option/filter_test.go +++ /dev/null @@ -1,17 +0,0 @@ -package option_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/stretchr/testify/assert" -) - -func TestOption_Filter(t *testing.T) { - var isEven = func(n int32) bool { - return n%2 == 0 - } - assert.Equal(t, gust.None[int32](), gust.None[int32]().Filter(isEven)) - assert.Equal(t, gust.None[int32](), gust.Some[int32](3).Filter(isEven)) - assert.Equal(t, gust.Some[int32](4), gust.Some[int32](4).Filter(isEven)) -} diff --git a/examples/option/get_or_insert_default_test.go b/examples/option/get_or_insert_default_test.go deleted file mode 100644 index 7a8a45f..0000000 --- a/examples/option/get_or_insert_default_test.go +++ /dev/null @@ -1,18 +0,0 @@ -package option_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/valconv" - "github.com/stretchr/testify/assert" -) - -func TestOption_GetOrInsertDefault(t *testing.T) { - none := gust.None[int]() - assert.Equal(t, valconv.Ref(0), none.GetOrInsertDefault()) - assert.Equal(t, valconv.Ref(0), none.AsPtr()) - some := gust.Some[int](1) - assert.Equal(t, valconv.Ref(1), some.GetOrInsertDefault()) - assert.Equal(t, valconv.Ref(1), some.AsPtr()) -} diff --git a/examples/option/get_or_insert_test.go b/examples/option/get_or_insert_test.go deleted file mode 100644 index 2ad173e..0000000 --- a/examples/option/get_or_insert_test.go +++ /dev/null @@ -1,16 +0,0 @@ -package option_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/stretchr/testify/assert" -) - -func TestOption_GetOrInsert(t *testing.T) { - var x = gust.None[int]() - var y = x.GetOrInsert(5) - assert.Equal(t, 5, *y) - *y = 7 - assert.Equal(t, 7, x.Unwrap()) -} diff --git a/examples/option/get_or_insert_with_test.go b/examples/option/get_or_insert_with_test.go deleted file mode 100644 index 8e34728..0000000 --- a/examples/option/get_or_insert_with_test.go +++ /dev/null @@ -1,24 +0,0 @@ -package option_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/stretchr/testify/assert" -) - -func TestOption_GetOrInsertWith(t *testing.T) { - var x = gust.None[int]() - var y = x.GetOrInsertWith(func() int { return 5 }) - assert.Equal(t, 5, *y) - assert.Equal(t, 5, x.Unwrap()) - *y = 7 - assert.Equal(t, 7, x.Unwrap()) - - var x2 = gust.None[int]() - var y2 = x2.GetOrInsertWith(nil) - assert.Equal(t, 0, *y2) - assert.Equal(t, 0, x2.Unwrap()) - *y2 = 7 - assert.Equal(t, 7, x2.Unwrap()) -} diff --git a/examples/option/insert_test.go b/examples/option/insert_test.go deleted file mode 100644 index 8b692e1..0000000 --- a/examples/option/insert_test.go +++ /dev/null @@ -1,19 +0,0 @@ -package option_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/stretchr/testify/assert" -) - -func TestOption_Insert(t *testing.T) { - var opt = gust.None[int]() - var val = opt.Insert(1) - assert.Equal(t, 1, *val) - assert.Equal(t, 1, opt.Unwrap()) - val = opt.Insert(2) - assert.Equal(t, 2, *val) - *val = 3 - assert.Equal(t, 3, opt.Unwrap()) -} diff --git a/examples/option/inspect_test.go b/examples/option/inspect_test.go deleted file mode 100644 index 23512fe..0000000 --- a/examples/option/inspect_test.go +++ /dev/null @@ -1,22 +0,0 @@ -package option_test - -import ( - "fmt" - - "github.com/andeya/gust" -) - -func ExampleOption_Inspect() { - // prints "got: 3" - _ = gust.Some(3).Inspect(func(x int) { - fmt.Println("got:", x) - }) - - // prints nothing - _ = gust.None[int]().Inspect(func(x int) { - fmt.Println("got:", x) - }) - - // Output: - // got: 3 -} diff --git a/examples/option/is_none_test.go b/examples/option/is_none_test.go deleted file mode 100644 index 69b457f..0000000 --- a/examples/option/is_none_test.go +++ /dev/null @@ -1,19 +0,0 @@ -package option_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/stretchr/testify/assert" -) - -func TestOption_IsNone(t *testing.T) { - { - var x = gust.Some[uint32](2) - assert.False(t, x.IsNone()) - } - { - var x = gust.None[uint32]() - assert.True(t, x.IsNone()) - } -} diff --git a/examples/option/is_some_and_test.go b/examples/option/is_some_and_test.go deleted file mode 100644 index 71d7e2c..0000000 --- a/examples/option/is_some_and_test.go +++ /dev/null @@ -1,23 +0,0 @@ -package option_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/stretchr/testify/assert" -) - -func TestOption_IsSomeAnd(t *testing.T) { - { - var x = gust.Some[uint32](2) - assert.True(t, x.IsSomeAnd(func(v uint32) bool { return v > 1 })) - } - { - var x = gust.Some[uint32](0) - assert.False(t, x.IsSomeAnd(func(v uint32) bool { return v > 1 })) - } - { - var x = gust.None[uint32]() - assert.False(t, x.IsSomeAnd(func(v uint32) bool { return v > 1 })) - } -} diff --git a/examples/option/is_some_test.go b/examples/option/is_some_test.go deleted file mode 100644 index b4ec6b2..0000000 --- a/examples/option/is_some_test.go +++ /dev/null @@ -1,19 +0,0 @@ -package option_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/stretchr/testify/assert" -) - -func TestOption_IsSome(t *testing.T) { - { - var x = gust.Some[uint32](2) - assert.True(t, x.IsSome()) - } - { - var x = gust.None[uint32]() - assert.False(t, x.IsSome()) - } -} diff --git a/examples/option/map_or_else_test.go b/examples/option/map_or_else_test.go deleted file mode 100644 index 91da48e..0000000 --- a/examples/option/map_or_else_test.go +++ /dev/null @@ -1,33 +0,0 @@ -package option_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/opt" - "github.com/stretchr/testify/assert" -) - -func TestOption_MapOrElse_1(t *testing.T) { - var k = 21 - { - var x = gust.Some("foo") - assert.Equal(t, 3, opt.MapOrElse(x, func() int { return 2 * k }, func(v string) int { return len(v) })) - } - { - var x gust.Option[string] - assert.Equal(t, 42, opt.MapOrElse(x, func() int { return 2 * k }, func(v string) int { return len(v) })) - } -} - -func TestOption_MapOrElse_2(t *testing.T) { - var k = 21 - { - var x = gust.Some("foo") - assert.Equal(t, 3, x.XMapOrElse(func() any { return 2 * k }, func(v string) any { return len(v) })) - } - { - var x gust.Option[string] - assert.Equal(t, 42, x.XMapOrElse(func() any { return 2 * k }, func(v string) any { return len(v) })) - } -} diff --git a/examples/option/map_or_test.go b/examples/option/map_or_test.go deleted file mode 100644 index 7ce5429..0000000 --- a/examples/option/map_or_test.go +++ /dev/null @@ -1,31 +0,0 @@ -package option_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/opt" - "github.com/stretchr/testify/assert" -) - -func TestOption_MapOr_1(t *testing.T) { - { - var x = gust.Some("foo") - assert.Equal(t, 3, opt.MapOr(x, 42, func(v string) int { return len(v) })) - } - { - var x gust.Option[string] - assert.Equal(t, 42, opt.MapOr(x, 42, func(v string) int { return len(v) })) - } -} - -func TestOption_MapOr_2(t *testing.T) { - { - var x = gust.Some("foo") - assert.Equal(t, 3, x.XMapOr(42, func(v string) any { return len(v) })) - } - { - var x gust.Option[string] - assert.Equal(t, 42, x.XMapOr(42, func(v string) any { return len(v) })) - } -} diff --git a/examples/option/map_test.go b/examples/option/map_test.go deleted file mode 100644 index 4be85d9..0000000 --- a/examples/option/map_test.go +++ /dev/null @@ -1,21 +0,0 @@ -package option_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/opt" - "github.com/stretchr/testify/assert" -) - -func TestOption_Map_1(t *testing.T) { - var maybeSomeString = gust.Some("Hello, World!") - var maybeSomeLen = opt.Map(maybeSomeString, func(s string) int { return len(s) }) - assert.Equal(t, maybeSomeLen, gust.Some(13)) -} - -func TestOption_Map_2(t *testing.T) { - var maybeSomeString = gust.Some("Hello, World!") - var maybeSomeLen = maybeSomeString.XMap(func(s string) any { return len(s) }) - assert.Equal(t, maybeSomeLen, gust.Some(13).ToX()) -} diff --git a/examples/option/ok_or_else_test.go b/examples/option/ok_or_else_test.go deleted file mode 100644 index 19134d9..0000000 --- a/examples/option/ok_or_else_test.go +++ /dev/null @@ -1,19 +0,0 @@ -package option_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/stretchr/testify/assert" -) - -func TestOption_OkOrElse(t *testing.T) { - { - var x = gust.Some("foo") - assert.Equal(t, gust.Ok("foo"), x.OkOrElse(func() any { return 0 })) - } - { - var x gust.Option[string] - assert.Equal(t, gust.Err[string](0), x.OkOrElse(func() any { return 0 })) - } -} diff --git a/examples/option/ok_or_test.go b/examples/option/ok_or_test.go deleted file mode 100644 index f4b7556..0000000 --- a/examples/option/ok_or_test.go +++ /dev/null @@ -1,19 +0,0 @@ -package option_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/stretchr/testify/assert" -) - -func TestOption_OkOr(t *testing.T) { - { - var x = gust.Some("foo") - assert.Equal(t, gust.Ok("foo"), x.OkOr(0)) - } - { - var x gust.Option[string] - assert.Equal(t, gust.Err[string](0), x.OkOr(0)) - } -} diff --git a/examples/option/option_overview_test.go b/examples/option/option_overview_test.go deleted file mode 100644 index 80b9e63..0000000 --- a/examples/option/option_overview_test.go +++ /dev/null @@ -1,69 +0,0 @@ -package option_test - -import ( - "fmt" - "strconv" - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/opt" -) - -func TestOption(t *testing.T) { - var divide = func(numerator, denominator float64) gust.Option[float64] { - if denominator == 0.0 { - return gust.None[float64]() - } - return gust.Some(numerator / denominator) - } - // The return value of the function is an option - divide(2.0, 3.0). - Inspect(func(x float64) { - // Pattern match to retrieve the value - t.Log("Result:", x) - }). - InspectNone(func() { - t.Log("Cannot divide by 0") - }) -} - -func ExampleOption() { - type A struct { - X int - } - var a = gust.Some(A{X: 1}) - fmt.Println(a.IsSome(), a.IsNone()) - - var b = gust.None[A]() - fmt.Println(b.IsSome(), b.IsNone()) - - var x = b.UnwrapOr(A{X: 2}) - fmt.Println(x) - - var c *A - fmt.Println(gust.PtrOpt(c).IsNone()) - fmt.Println(gust.ElemOpt(c).IsNone()) - c = new(A) - fmt.Println(gust.PtrOpt(c).IsNone()) - fmt.Println(gust.ElemOpt(c).IsNone()) - - type B struct { - Y string - } - var d = opt.Map(a, func(t A) B { - return B{ - Y: strconv.Itoa(t.X), - } - }) - fmt.Println(d) - - // Output: - // true false - // false true - // {2} - // true - // true - // false - // false - // Some({1}) -} diff --git a/examples/option/or_else_test.go b/examples/option/or_else_test.go deleted file mode 100644 index 183c02b..0000000 --- a/examples/option/or_else_test.go +++ /dev/null @@ -1,16 +0,0 @@ -package option_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/stretchr/testify/assert" -) - -func TestOption_OrElse(t *testing.T) { - var nobody = func() gust.Option[string] { return gust.None[string]() } - var vikings = func() gust.Option[string] { return gust.Some("vikings") } - assert.Equal(t, gust.Some("barbarians"), gust.Some("barbarians").OrElse(vikings)) - assert.Equal(t, gust.Some("vikings"), gust.None[string]().OrElse(vikings)) - assert.Equal(t, gust.None[string](), gust.None[string]().OrElse(nobody)) -} diff --git a/examples/option/or_test.go b/examples/option/or_test.go deleted file mode 100644 index 656f915..0000000 --- a/examples/option/or_test.go +++ /dev/null @@ -1,31 +0,0 @@ -package option_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/stretchr/testify/assert" -) - -func TestOption_Or(t *testing.T) { - { - var x = gust.Some[uint32](2) - var y gust.Option[uint32] - assert.Equal(t, gust.Some[uint32](2), x.Or(y)) - } - { - var x gust.Option[uint32] - var y = gust.Some[uint32](100) - assert.Equal(t, gust.Some[uint32](100), x.Or(y)) - } - { - var x = gust.Some[uint32](2) - var y = gust.Some[uint32](100) - assert.Equal(t, gust.Some[uint32](2), x.Or(y)) - } - { - var x gust.Option[uint32] - var y = gust.None[uint32]() - assert.Equal(t, gust.None[uint32](), x.Or(y)) - } -} diff --git a/examples/option/replace_test.go b/examples/option/replace_test.go deleted file mode 100644 index 5027f5c..0000000 --- a/examples/option/replace_test.go +++ /dev/null @@ -1,23 +0,0 @@ -package option_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/stretchr/testify/assert" -) - -func TestOption_Replace(t *testing.T) { - { - var x = gust.Some(2) - var old = x.Replace(5) - assert.Equal(t, gust.Some(5), x) - assert.Equal(t, gust.Some(2), old) - } - { - var x = gust.None[int]() - var old = x.Replace(3) - assert.Equal(t, gust.Some(3), x) - assert.Equal(t, gust.None[int](), old) - } -} diff --git a/examples/option/take_test.go b/examples/option/take_test.go deleted file mode 100644 index 781a9eb..0000000 --- a/examples/option/take_test.go +++ /dev/null @@ -1,23 +0,0 @@ -package option_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/stretchr/testify/assert" -) - -func TestOption_Take(t *testing.T) { - { - var x = gust.Some(2) - var y = x.Take() - assert.True(t, x.IsNone()) - assert.Equal(t, gust.Some(2), y) - } - { - var x gust.Option[int] = gust.None[int]() - var y = x.Take() - assert.True(t, x.IsNone()) - assert.True(t, y.IsNone()) - } -} diff --git a/examples/option/unwrap_or_default_test.go b/examples/option/unwrap_or_default_test.go deleted file mode 100644 index 5fd2f1b..0000000 --- a/examples/option/unwrap_or_default_test.go +++ /dev/null @@ -1,18 +0,0 @@ -package option_test - -import ( - "testing" - "time" - - "github.com/andeya/gust" - "github.com/andeya/gust/valconv" - "github.com/stretchr/testify/assert" -) - -func TestOption_UnwrapOrDefault(t *testing.T) { - assert.Equal(t, "car", gust.Some("car").UnwrapOrDefault()) - assert.Equal(t, "", gust.None[string]().UnwrapOrDefault()) - assert.Equal(t, time.Time{}, gust.None[time.Time]().UnwrapOrDefault()) - assert.Equal(t, &time.Time{}, gust.None[*time.Time]().UnwrapOrDefault()) - assert.Equal(t, valconv.Ref(&time.Time{}), gust.None[**time.Time]().UnwrapOrDefault()) -} diff --git a/examples/option/unwrap_or_else_test.go b/examples/option/unwrap_or_else_test.go deleted file mode 100644 index 7f6322f..0000000 --- a/examples/option/unwrap_or_else_test.go +++ /dev/null @@ -1,14 +0,0 @@ -package option_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/stretchr/testify/assert" -) - -func TestOption_UnwrapOrElse(t *testing.T) { - var k = 10 - assert.Equal(t, 4, gust.Some(4).UnwrapOrElse(func() int { return 2 * k })) - assert.Equal(t, 20, gust.None[int]().UnwrapOrElse(func() int { return 2 * k })) -} diff --git a/examples/option/unwrap_or_test.go b/examples/option/unwrap_or_test.go deleted file mode 100644 index 0816890..0000000 --- a/examples/option/unwrap_or_test.go +++ /dev/null @@ -1,13 +0,0 @@ -package option_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/stretchr/testify/assert" -) - -func TestOption_UnwrapOr(t *testing.T) { - assert.Equal(t, "car", gust.Some("car").UnwrapOr("bike")) - assert.Equal(t, "bike", gust.None[string]().UnwrapOr("bike")) -} diff --git a/examples/option/unwrap_test.go b/examples/option/unwrap_test.go deleted file mode 100644 index 6bc8a38..0000000 --- a/examples/option/unwrap_test.go +++ /dev/null @@ -1,20 +0,0 @@ -package option_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/stretchr/testify/assert" -) - -func TestOption_Unwrap(t *testing.T) { - { - var x = gust.Some("air") - assert.Equal(t, "air", x.Unwrap()) - } - defer func() { - assert.Equal(t, gust.ToErrBox("call Option[string].Unwrap() on none"), recover()) - }() - var x = gust.None[string]() - x.Unwrap() -} diff --git a/examples/option/unzip_test.go b/examples/option/unzip_test.go deleted file mode 100644 index 5a7e8bb..0000000 --- a/examples/option/unzip_test.go +++ /dev/null @@ -1,16 +0,0 @@ -package option_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/opt" - "github.com/stretchr/testify/assert" -) - -func TestOption_Unzip(t *testing.T) { - var x = gust.Some[gust.Pair[int, string]](gust.Pair[int, string]{A: 1, B: "hi"}) - var y = gust.None[gust.Pair[int, string]]() - assert.Equal(t, opt.Unzip(x), gust.Pair[gust.Option[int], gust.Option[string]]{A: gust.Some[int](1), B: gust.Some[string]("hi")}) - assert.Equal(t, opt.Unzip(y), gust.Pair[gust.Option[int], gust.Option[string]]{A: gust.None[int](), B: gust.None[string]()}) -} diff --git a/examples/option/xor_test.go b/examples/option/xor_test.go deleted file mode 100644 index f030f64..0000000 --- a/examples/option/xor_test.go +++ /dev/null @@ -1,31 +0,0 @@ -package option_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/stretchr/testify/assert" -) - -func TestOption_Xor(t *testing.T) { - { - var x = gust.Some[uint32](2) - var y gust.Option[uint32] - assert.Equal(t, gust.Some[uint32](2), x.Xor(y)) - } - { - var x gust.Option[uint32] - var y = gust.Some[uint32](100) - assert.Equal(t, gust.Some[uint32](100), x.Xor(y)) - } - { - var x = gust.Some[uint32](2) - var y = gust.Some[uint32](100) - assert.Equal(t, gust.None[uint32](), x.Xor(y)) - } - { - var x gust.Option[uint32] - var y = gust.None[uint32]() - assert.Equal(t, gust.None[uint32](), x.Xor(y)) - } -} diff --git a/examples/option/zip_test.go b/examples/option/zip_test.go deleted file mode 100644 index 4311d4c..0000000 --- a/examples/option/zip_test.go +++ /dev/null @@ -1,17 +0,0 @@ -package option_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/opt" - "github.com/stretchr/testify/assert" -) - -func TestOption_Zip(t *testing.T) { - var x = gust.Some[byte](1) - var y = gust.Some("hi") - var z = gust.None[byte]() - assert.Equal(t, gust.Some(gust.Pair[byte, string]{1, "hi"}), opt.Zip(x, y)) - assert.Equal(t, gust.None[gust.Pair[byte, byte]](), opt.Zip(x, z)) -} diff --git a/examples/option/zip_with_test.go b/examples/option/zip_with_test.go deleted file mode 100644 index c3a998f..0000000 --- a/examples/option/zip_with_test.go +++ /dev/null @@ -1,23 +0,0 @@ -package option_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/opt" - "github.com/stretchr/testify/assert" -) - -func TestOption_ZipWith(t *testing.T) { - type Point struct { - x float64 - y float64 - } - var newPoint = func(x float64, y float64) Point { - return Point{x, y} - } - var x = gust.Some(17.5) - var y = gust.Some(42.7) - assert.Equal(t, opt.ZipWith(x, y, newPoint), gust.Some(Point{x: 17.5, y: 42.7})) - assert.Equal(t, opt.ZipWith(x, gust.None[float64](), newPoint), gust.None[Point]()) -} diff --git a/examples/result/and_test.go b/examples/result/and_test.go deleted file mode 100644 index 20c0ba4..0000000 --- a/examples/result/and_test.go +++ /dev/null @@ -1,21 +0,0 @@ -package result_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/stretchr/testify/assert" -) - -func TestResult_And(t *testing.T) { - { - x := gust.Ok(2) - y := gust.Err[int]("late error") - assert.Equal(t, gust.Err[int]("late error"), x.And(y)) - } - { - x := gust.Err[uint]("early error") - y := gust.Ok[string]("foo") - assert.Equal(t, gust.Err[any]("early error"), x.XAnd(y.ToX())) - } -} diff --git a/examples/result/and_then_test.go b/examples/result/and_then_test.go deleted file mode 100644 index c976c81..0000000 --- a/examples/result/and_then_test.go +++ /dev/null @@ -1,22 +0,0 @@ -package result_test - -import ( - "fmt" - - "github.com/andeya/gust" -) - -func ExampleResult_AndThen() { - var divide = func(i, j float32) gust.Result[float32] { - if j == 0 { - return gust.Err[float32]("j can not be 0") - } - return gust.Ok(i / j) - } - var ret float32 = divide(1, 2).AndThen(func(i float32) gust.Result[float32] { - return gust.Ok(i * 10) - }).Unwrap() - fmt.Println(ret) - // Output: - // 5 -} diff --git a/examples/result/assert_test.go b/examples/result/assert_test.go deleted file mode 100644 index cbcf261..0000000 --- a/examples/result/assert_test.go +++ /dev/null @@ -1,20 +0,0 @@ -package result_test - -import ( - "fmt" - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/ret" - "github.com/stretchr/testify/assert" -) - -func TestAssert(t *testing.T) { - r := gust.Ok[any]("hello") - assert.Equal(t, "gust.Result[string]", fmt.Sprintf("%T", ret.Assert[any, string](r))) -} - -func TestXAssert(t *testing.T) { - r := gust.Ok[any]("hello") - assert.Equal(t, "gust.Result[string]", fmt.Sprintf("%T", ret.XAssert[string](r))) -} diff --git a/examples/result/contains_err_test.go b/examples/result/contains_err_test.go deleted file mode 100644 index e843cf0..0000000 --- a/examples/result/contains_err_test.go +++ /dev/null @@ -1,16 +0,0 @@ -package result_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/ret" - "github.com/stretchr/testify/assert" -) - -func TestResult_ContainsErr(t *testing.T) { - assert.False(t, gust.Ok(2).ContainsErr("Some error message")) - assert.True(t, ret.Contains(gust.Ok(2), 2)) - assert.False(t, ret.Contains(gust.Ok(3), 2)) - assert.False(t, ret.Contains(gust.Err[int]("Some error message"), 2)) -} diff --git a/examples/result/contains_test.go b/examples/result/contains_test.go deleted file mode 100644 index 267702d..0000000 --- a/examples/result/contains_test.go +++ /dev/null @@ -1,15 +0,0 @@ -package result_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/ret" - "github.com/stretchr/testify/assert" -) - -func TestResult_Contains(t *testing.T) { - assert.True(t, ret.Contains(gust.Ok(2), 2)) - assert.False(t, ret.Contains(gust.Ok(3), 2)) - assert.False(t, ret.Contains(gust.Err[int]("Some error message"), 2)) -} diff --git a/examples/result/err_test.go b/examples/result/err_test.go deleted file mode 100644 index 1d667f9..0000000 --- a/examples/result/err_test.go +++ /dev/null @@ -1,30 +0,0 @@ -package result_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/stretchr/testify/assert" -) - -func TestResult_Err(t *testing.T) { - { - var x = gust.Ok[int](2) - assert.Equal(t, error(nil), x.Err()) - } - { - var x = gust.Err[int]("some error message") - assert.Equal(t, "some error message", x.Err().Error()) - } -} - -func TestEnumResult_Err(t *testing.T) { - { - var x = gust.EnumOk[int, string](2) - assert.Equal(t, gust.None[string](), x.Err()) - } - { - var x = gust.EnumErr[int, string]("some error message") - assert.Equal(t, gust.Some[string]("some error message"), x.Err()) - } -} diff --git a/examples/result/expect_err_test.go b/examples/result/expect_err_test.go deleted file mode 100644 index 867c9bb..0000000 --- a/examples/result/expect_err_test.go +++ /dev/null @@ -1,16 +0,0 @@ -package result_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/stretchr/testify/assert" -) - -func TestExpectErr(t *testing.T) { - defer func() { - assert.Equal(t, gust.ToErrBox("Testing expect_err: 10"), recover()) - }() - err := gust.Ok(10).ExpectErr("Testing expect_err") - assert.NoError(t, err) -} diff --git a/examples/result/expect_test.go b/examples/result/expect_test.go deleted file mode 100644 index 0e1afdf..0000000 --- a/examples/result/expect_test.go +++ /dev/null @@ -1,18 +0,0 @@ -package result_test - -import ( - "strconv" - "testing" - - "github.com/andeya/gust" - "github.com/stretchr/testify/assert" -) - -func TestExpect(t *testing.T) { - defer func() { - assert.Equal(t, "failed to parse number: strconv.Atoi: parsing \"4x\": invalid syntax", recover().(error).Error()) - }() - gust.Ret(strconv.Atoi("4x")). - Expect("failed to parse number") - -} diff --git a/examples/result/inspect_err_test.go b/examples/result/inspect_err_test.go deleted file mode 100644 index 5a21710..0000000 --- a/examples/result/inspect_err_test.go +++ /dev/null @@ -1,15 +0,0 @@ -package result_test - -import ( - "strconv" - "testing" - - "github.com/andeya/gust" -) - -func TestInspectErr(t *testing.T) { - gust.Ret(strconv.Atoi("4x")). - InspectErr(func(err error) { - t.Logf("failed to convert: %v", err) - }) -} diff --git a/examples/result/inspect_test.go b/examples/result/inspect_test.go deleted file mode 100644 index 2d20fb9..0000000 --- a/examples/result/inspect_test.go +++ /dev/null @@ -1,20 +0,0 @@ -package result_test - -import ( - "fmt" - "strconv" - "testing" - - "github.com/andeya/gust" -) - -func TestInspect(t *testing.T) { - gust.Ret(strconv.Atoi("4")). - Inspect(func(x int) { - fmt.Println("original: ", x) - }). - Map(func(x int) int { - return x * 3 - }). - Expect("failed to parse number") -} diff --git a/examples/result/is_err_and_test.go b/examples/result/is_err_and_test.go deleted file mode 100644 index 0332964..0000000 --- a/examples/result/is_err_and_test.go +++ /dev/null @@ -1,26 +0,0 @@ -package result_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/stretchr/testify/assert" -) - -func TestResult_IsErrAnd(t *testing.T) { - { - var x = gust.Err[int]("hey") - assert.True(t, x.IsErrAnd(func(err error) bool { return err.Error() == "hey" })) - } - { - var x = gust.Ok[int](2) - assert.False(t, x.IsErrAnd(func(err error) bool { return err.Error() == "hey" })) - } -} - -func TestEnumResult_IsErrAnd(t *testing.T) { - { - var x = gust.EnumErr[int, int8](-1) - assert.True(t, x.IsErrAnd(func(x int8) bool { return x == -1 })) - } -} diff --git a/examples/result/is_err_test.go b/examples/result/is_err_test.go deleted file mode 100644 index a9e5241..0000000 --- a/examples/result/is_err_test.go +++ /dev/null @@ -1,19 +0,0 @@ -package result_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/stretchr/testify/assert" -) - -func TestResult_IsErr(t *testing.T) { - { - var x = gust.Ok[int](-3) - assert.False(t, x.IsErr()) - } - { - var x = gust.Err[int]("some error message") - assert.True(t, x.IsErr()) - } -} diff --git a/examples/result/is_ok_and_test.go b/examples/result/is_ok_and_test.go deleted file mode 100644 index ec23067..0000000 --- a/examples/result/is_ok_and_test.go +++ /dev/null @@ -1,23 +0,0 @@ -package result_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/stretchr/testify/assert" -) - -func TestResult_IsOkAnd(t *testing.T) { - { - var x = gust.Ok[int](2) - assert.True(t, x.IsOkAnd(func(x int) bool { return x > 1 })) - } - { - var x = gust.Ok[int](0) - assert.False(t, x.IsOkAnd(func(x int) bool { return x > 1 })) - } - { - var x = gust.Err[int]("hey") - assert.False(t, x.IsOkAnd(func(x int) bool { return x > 1 })) - } -} diff --git a/examples/result/is_ok_test.go b/examples/result/is_ok_test.go deleted file mode 100644 index ed726d4..0000000 --- a/examples/result/is_ok_test.go +++ /dev/null @@ -1,19 +0,0 @@ -package result_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/stretchr/testify/assert" -) - -func TestResult_IsOk(t *testing.T) { - { - var x = gust.Ok[int](-3) - assert.True(t, x.IsOk()) - } - { - var x = gust.Err[int]("some error message") - assert.False(t, x.IsOk()) - } -} diff --git a/examples/result/map_err_test.go b/examples/result/map_err_test.go deleted file mode 100644 index 5c23bf0..0000000 --- a/examples/result/map_err_test.go +++ /dev/null @@ -1,21 +0,0 @@ -package result_test - -import ( - "fmt" - "testing" - - "github.com/andeya/gust" - "github.com/stretchr/testify/assert" -) - -func TestResult_MapErr(t *testing.T) { - var stringify = func(x error) any { return fmt.Sprintf("error code: %v", x) } - { - var x = gust.Ok[uint32](2) - assert.Equal(t, gust.Ok[uint32](2), x.MapErr(stringify)) - } - { - var x = gust.Err[uint32](13) - assert.Equal(t, gust.Err[uint32]("error code: 13"), x.MapErr(stringify)) - } -} diff --git a/examples/result/map_or_else_test.go b/examples/result/map_or_else_test.go deleted file mode 100644 index 77d48be..0000000 --- a/examples/result/map_or_else_test.go +++ /dev/null @@ -1,40 +0,0 @@ -package result_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/ret" - "github.com/stretchr/testify/assert" -) - -func TestResult_MapOrElse_1(t *testing.T) { - var k = 21 - { - var x = gust.Ok("foo") - assert.Equal(t, 3, ret.MapOrElse(x, func(err error) int { - return k * 2 - }, func(x string) int { return len(x) })) - } - { - var x = gust.Err[string]("bar") - assert.Equal(t, 42, ret.MapOrElse(x, func(err error) int { - return k * 2 - }, func(x string) int { return len(x) })) - } -} - -func TestResult_MapOrElse_2(t *testing.T) { - { - var x = gust.Ok("foo") - assert.Equal(t, "test:foo", x.MapOrElse(func(err error) string { - return "bar" - }, func(x string) string { return "test:" + x })) - } - { - var x = gust.Err[string]("foo") - assert.Equal(t, "bar", x.MapOrElse(func(err error) string { - return "bar" - }, func(x string) string { return "test:" + x })) - } -} diff --git a/examples/result/map_or_test.go b/examples/result/map_or_test.go deleted file mode 100644 index 19189ea..0000000 --- a/examples/result/map_or_test.go +++ /dev/null @@ -1,31 +0,0 @@ -package result_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/ret" - "github.com/stretchr/testify/assert" -) - -func TestResult_MapOr_1(t *testing.T) { - { - var x = gust.Ok("foo") - assert.Equal(t, 3, ret.MapOr(x, 42, func(x string) int { return len(x) })) - } - { - var x = gust.Err[string]("foo") - assert.Equal(t, 42, ret.MapOr(x, 42, func(x string) int { return len(x) })) - } -} - -func TestResult_MapOr_2(t *testing.T) { - { - var x = gust.Ok("foo") - assert.Equal(t, "test:foo", x.MapOr("bar", func(x string) string { return "test:" + x })) - } - { - var x = gust.Err[string]("foo") - assert.Equal(t, "bar", x.MapOr("bar", func(x string) string { return "test:" + x })) - } -} diff --git a/examples/result/map_test.go b/examples/result/map_test.go deleted file mode 100644 index 2c9efa9..0000000 --- a/examples/result/map_test.go +++ /dev/null @@ -1,41 +0,0 @@ -package result_test - -import ( - "strconv" - "strings" - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/ret" - "github.com/stretchr/testify/assert" -) - -func TestResult_Map_1(t *testing.T) { - var line = "1\n2\n3\n4\n" - for _, num := range strings.Split(line, "\n") { - gust.Ret(strconv.Atoi(num)).Map(func(i int) int { - return i * 2 - }).Inspect(func(i int) { - t.Log(i) - }) - } -} - -func TestResult_Map_2(t *testing.T) { - var isMyNum = func(s string, search int) gust.Result[any] { - return gust.Ret(strconv.Atoi(s)).XMap(func(x int) any { return x == search }) - } - assert.Equal(t, gust.Ok[any](true), isMyNum("1", 1)) - assert.Equal(t, gust.Ok[bool](true), ret.XAssert[bool](isMyNum("1", 1))) - assert.Equal(t, "Err(strconv.Atoi: parsing \"lol\": invalid syntax)", isMyNum("lol", 1).String()) - assert.Equal(t, "Err(strconv.Atoi: parsing \"NaN\": invalid syntax)", isMyNum("NaN", 1).String()) -} - -func TestResult_Map_3(t *testing.T) { - var isMyNum = func(s string, search int) gust.Result[bool] { - return ret.Map(gust.Ret(strconv.Atoi(s)), func(x int) bool { return x == search }) - } - assert.Equal(t, gust.Ok[bool](true), isMyNum("1", 1)) - assert.Equal(t, "Err(strconv.Atoi: parsing \"lol\": invalid syntax)", isMyNum("lol", 1).String()) - assert.Equal(t, "Err(strconv.Atoi: parsing \"NaN\": invalid syntax)", isMyNum("NaN", 1).String()) -} diff --git a/examples/result/ok_test.go b/examples/result/ok_test.go deleted file mode 100644 index 0b96c49..0000000 --- a/examples/result/ok_test.go +++ /dev/null @@ -1,19 +0,0 @@ -package result_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/stretchr/testify/assert" -) - -func TestResult_Ok(t *testing.T) { - { - var x = gust.Ok[int](2) - assert.Equal(t, gust.Some[int](2), x.Ok()) - } - { - var x = gust.Err[int]("some error message") - assert.Equal(t, gust.None[int](), x.Ok()) - } -} diff --git a/examples/result/or_else_test.go b/examples/result/or_else_test.go deleted file mode 100644 index 1207531..0000000 --- a/examples/result/or_else_test.go +++ /dev/null @@ -1,22 +0,0 @@ -package result_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/stretchr/testify/assert" -) - -func TestResult_OrElse(t *testing.T) { - var sq = func(x int) gust.EnumResult[int, int] { - return gust.EnumOk[int, int](x * x) - } - var err = func(x int) gust.EnumResult[int, int] { - return gust.EnumErr[int, int](x) - } - - assert.Equal(t, gust.EnumOk[int, int](2).OrElse(sq).OrElse(sq), gust.EnumOk[int, int](2)) - assert.Equal(t, gust.EnumOk[int, int](2).OrElse(err).OrElse(sq), gust.EnumOk[int, int](2)) - assert.Equal(t, gust.EnumErr[int, int](3).OrElse(sq).OrElse(err), gust.EnumOk[int, int](9)) - assert.Equal(t, gust.EnumErr[int, int](3).OrElse(err).OrElse(err), gust.EnumErr[int, int](3)) -} diff --git a/examples/result/or_test.go b/examples/result/or_test.go deleted file mode 100644 index 3f78ad0..0000000 --- a/examples/result/or_test.go +++ /dev/null @@ -1,31 +0,0 @@ -package result_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/stretchr/testify/assert" -) - -func TestResult_Or(t *testing.T) { - { - x := gust.Ok(2) - y := gust.Err[int]("late error") - assert.Equal(t, gust.Ok(2), x.Or(y)) - } - { - x := gust.Err[uint]("early error") - y := gust.Ok[uint](2) - assert.Equal(t, gust.Ok[uint](2), x.Or(y)) - } - { - x := gust.Err[uint]("not a 2") - y := gust.Err[uint]("late error") - assert.Equal(t, gust.Err[uint]("late error"), x.Or(y)) - } - { - x := gust.Ok[uint](2) - y := gust.Ok[uint](100) - assert.Equal(t, gust.Ok[uint](2), x.Or(y)) - } -} diff --git a/examples/result/result_overview_test.go b/examples/result/result_overview_test.go deleted file mode 100644 index 2c1943b..0000000 --- a/examples/result/result_overview_test.go +++ /dev/null @@ -1,36 +0,0 @@ -package result_test - -import ( - "fmt" - "testing" - - "github.com/andeya/gust" - "github.com/andeya/gust/ret" - "github.com/stretchr/testify/assert" -) - -// [`Result`] comes with some convenience methods that make working with it more succinct. -func TestResult(t *testing.T) { - var goodResult1 = gust.Ok(10) - var badResult1 = gust.Err[int](10) - - // The `IsOk` and `IsErr` methods do what they say. - assert.True(t, goodResult1.IsOk() && !goodResult1.IsErr()) - assert.True(t, badResult1.IsErr() && !badResult1.IsOk()) - - // `map` consumes the `Result` and produces another. - var goodResult2 = goodResult1.Map(func(i int) int { return i + 1 }) - var badResult2 = badResult1.Map(func(i int) int { return i - 1 }) - - // Use `AndThen` to continue the computation. - var goodResult3 = ret.AndThen(goodResult2, func(i int) gust.Result[bool] { return gust.Ok(i == 11) }) - - // Use `OrElse` to handle the error. - var _ = badResult2.OrElse(func(err error) gust.Result[int] { - fmt.Println(err) - return gust.Ok(20) - }) - - // Consume the result and return the contents with `Unwrap`. - var _ = goodResult3.Unwrap() -} diff --git a/examples/result/ret_test.go b/examples/result/ret_test.go deleted file mode 100644 index e7647e6..0000000 --- a/examples/result/ret_test.go +++ /dev/null @@ -1,20 +0,0 @@ -package result_test - -import ( - "strconv" - "testing" - - "github.com/andeya/gust" - "github.com/stretchr/testify/assert" -) - -func TestResult_Ret(t *testing.T) { - var w = gust.Ret[int](strconv.Atoi("s")) - assert.False(t, w.IsOk()) - assert.True(t, w.IsErr()) - - var w2 = gust.Ret[any](strconv.Atoi("-1")) - assert.True(t, w2.IsOk()) - assert.False(t, w2.IsErr()) - assert.Equal(t, -1, w2.Unwrap()) -} diff --git a/examples/result/unwrap_err_test.go b/examples/result/unwrap_err_test.go deleted file mode 100644 index 82581e1..0000000 --- a/examples/result/unwrap_err_test.go +++ /dev/null @@ -1,25 +0,0 @@ -package result_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/stretchr/testify/assert" -) - -func TestUnwrapErr_1(t *testing.T) { - defer func() { - assert.Equal(t, gust.ToErrBox("called `Result.UnwrapErr()` on an `ok` value: 10"), recover()) - }() - err := gust.Ok(10).UnwrapErr() - assert.NoError(t, err) -} - -func TestUnwrapErr_2(t *testing.T) { - err := gust.Err[int]("emergency failure").UnwrapErr() - if assert.Error(t, err) { - assert.Equal(t, "emergency failure", err.Error()) - } else { - t.FailNow() - } -} diff --git a/examples/result/unwrap_or_default_test.go b/examples/result/unwrap_or_default_test.go deleted file mode 100644 index f72e90d..0000000 --- a/examples/result/unwrap_or_default_test.go +++ /dev/null @@ -1,18 +0,0 @@ -package result_test - -import ( - "testing" - "time" - - "github.com/andeya/gust" - "github.com/andeya/gust/valconv" - "github.com/stretchr/testify/assert" -) - -func TestUnwrapOrDefault(t *testing.T) { - assert.Equal(t, "car", gust.Ok("car").UnwrapOrDefault()) - assert.Equal(t, "", gust.Err[string](nil).UnwrapOrDefault()) - assert.Equal(t, time.Time{}, gust.Err[time.Time](nil).UnwrapOrDefault()) - assert.Equal(t, &time.Time{}, gust.Err[*time.Time](nil).UnwrapOrDefault()) - assert.Equal(t, valconv.Ref(&time.Time{}), gust.Err[**time.Time](nil).UnwrapOrDefault()) -} diff --git a/examples/result/unwrap_or_else_test.go b/examples/result/unwrap_or_else_test.go deleted file mode 100644 index 708ca29..0000000 --- a/examples/result/unwrap_or_else_test.go +++ /dev/null @@ -1,16 +0,0 @@ -package result_test - -import ( - "testing" - - "github.com/andeya/gust" - "github.com/stretchr/testify/assert" -) - -func TestUnwrapOrElse(t *testing.T) { - var count = func(x error) int { - return len(x.Error()) - } - assert.Equal(t, 2, gust.Ok(2).UnwrapOrElse(count)) - assert.Equal(t, 3, gust.Err[int]("foo").UnwrapOrElse(count)) -} diff --git a/examples/result/unwrap_or_test.go b/examples/result/unwrap_or_test.go deleted file mode 100644 index e0e23da..0000000 --- a/examples/result/unwrap_or_test.go +++ /dev/null @@ -1,26 +0,0 @@ -package result_test - -import ( - "fmt" - "strconv" - - "github.com/andeya/gust" -) - -func ExampleResult_UnwrapOr() { - const def int = 10 - - // before - i, err := strconv.Atoi("1") - if err != nil { - i = def - } - fmt.Println(i * 2) - - // now - fmt.Println(gust.Ret(strconv.Atoi("1")).UnwrapOr(def) * 2) - - // Output: - // 2 - // 2 -} diff --git a/examples/result/unwrap_test.go b/examples/result/unwrap_test.go deleted file mode 100644 index d132257..0000000 --- a/examples/result/unwrap_test.go +++ /dev/null @@ -1,16 +0,0 @@ -package result_test - -import ( - "strconv" - "testing" - - "github.com/andeya/gust" - "github.com/stretchr/testify/assert" -) - -func TestUnwrap(t *testing.T) { - defer func() { - assert.Equal(t, "strconv.Atoi: parsing \"4x\": invalid syntax", recover().(error).Error()) - }() - gust.Ret(strconv.Atoi("4x")).Unwrap() -} diff --git a/iter/export_test.go b/iter/export_test.go index e651d62..63f4fdb 100644 --- a/iter/export_test.go +++ b/iter/export_test.go @@ -1,14 +1,62 @@ -package iter +package iter_test import ( + "fmt" + "strconv" "testing" "github.com/andeya/gust" + "github.com/andeya/gust/digit" + "github.com/andeya/gust/iter" + "github.com/andeya/gust/ret" "github.com/stretchr/testify/assert" ) +func TestAdvanceBy(t *testing.T) { + var c = make(chan int, 4) + c <- 1 + c <- 2 + c <- 3 + c <- 4 + close(c) + for _, i := range []iter.Iterator[int]{ + iter.FromElements(1, 2, 3, 4), + iter.FromRange(1, 4, true), + iter.FromChan(c), + } { + assert.Equal(t, gust.NonErrable[uint](), i.AdvanceBy(2)) + assert.Equal(t, gust.Some(3), i.Next()) + assert.Equal(t, gust.NonErrable[uint](), i.AdvanceBy(0)) + assert.Equal(t, gust.ToErrable[uint](1), i.AdvanceBy(100)) // only `4` was skipped + } +} + +func TestAll_1(t *testing.T) { + var a = []int8{1, 2, 3} + var all = iter.FromVec[int8](a).All(func(v int8) bool { + return v > 0 + }) + assert.True(t, all) + all = iter.FromVec[int8](a).All(func(v int8) bool { + return v > 2 + }) + assert.False(t, all) +} + +func TestAll_2(t *testing.T) { + var a = []int8{1, 2, 3} + var i = iter.FromVec[int8](a) + var all = i.All(func(v int8) bool { + return v != 2 + }) + assert.False(t, all) + // we can still use `i`, as there are more elements. + var next = i.Next() + assert.Equal(t, gust.Some(int8(3)), next) +} + func TestAny(t *testing.T) { - var iter = FromVec([]int{1, 2, 3}) + var iter = iter.FromVec([]int{1, 2, 3}) if !iter.Any(func(x int) bool { return x > 1 }) { @@ -16,48 +64,1023 @@ func TestAny(t *testing.T) { } } +func TestAny_1(t *testing.T) { + var a = []int8{1, 2, 3} + var hasAny = iter.FromVec[int8](a).Any(func(v int8) bool { + return v > 0 + }) + assert.True(t, hasAny) + hasAny = iter.FromVec[int8](a).Any(func(v int8) bool { + return v > 5 + }) + assert.False(t, hasAny) +} + +func TestAny_2(t *testing.T) { + var a = []int8{1, 2, 3} + var i = iter.FromVec[int8](a) + var hasAny = i.Any(func(v int8) bool { + return v != 2 + }) + assert.True(t, hasAny) + // we can still use `i`, as there are more elements. + var next = i.Next() + assert.Equal(t, gust.Some(int8(2)), next) +} + +func TestChain(t *testing.T) { + var c = make(chan int, 3) + c <- 4 + c <- 5 + c <- 6 + close(c) + for _, x := range [][2]iter.Iterator[int]{ + {iter.FromElements(1, 2, 3), iter.FromElements(4, 5, 6)}, + {iter.FromRange(1, 4), iter.FromChan(c)}, + } { + var i = x[0].ToChain(x[1]) + assert.Equal(t, gust.Some(1), i.Next()) + assert.Equal(t, gust.Some(2), i.Next()) + assert.Equal(t, gust.Some(3), i.Next()) + assert.Equal(t, gust.Some(4), i.Next()) + assert.Equal(t, gust.Some(5), i.Next()) + assert.Equal(t, gust.Some(6), i.Next()) + assert.Equal(t, gust.None[int](), i.Next()) + } +} + +func TestCount_1(t *testing.T) { + assert.Equal(t, uint(3), iter.FromElements(1, 2, 3).Count()) + assert.Equal(t, uint(5), iter.FromElements(1, 2, 3, 4, 5).Count()) +} + +func TestCount_2(t *testing.T) { + assert.Equal(t, uint(3), iter.FromRange(1, 3, true).Count()) + assert.Equal(t, uint(5), iter.FromRange(1, 6, false).Count()) + assert.Equal(t, uint(5), iter.FromRange(1, 6).Count()) +} + +func TestCount_3(t *testing.T) { + var c = make(chan int, 3) + c <- 1 + c <- 2 + c <- 3 + assert.Equal(t, uint(3), iter.FromChan(c).Count()) +} + +func TestEnumerate(t *testing.T) { + var i = iter.EnumElements[rune]('a', 'b', 'c') + assert.Equal(t, gust.Some(gust.VecEntry[rune]{ + Index: 0, Elem: 'a', + }), i.Next()) + assert.Equal(t, gust.Some(gust.VecEntry[rune]{ + Index: 1, Elem: 'b', + }), i.Next()) + assert.Equal(t, gust.Some(gust.VecEntry[rune]{ + Index: 2, Elem: 'c', + }), i.Next()) + assert.Equal(t, gust.None[gust.VecEntry[rune]](), i.Next()) +} + +func TestFilterMap_1(t *testing.T) { + var c = make(chan string, 10) + for idx, i := range []iter.Iterator[string]{ + iter.FromElements("1", "two", "NaN", "four", "5"), + iter.FromChan(c), + } { + var i = iter.ToFilterMap[string, int](i.ToInspect(func(v string) { + if idx == 0 { + c <- v + } + }), func(v string) gust.Option[int] { return gust.Ret(strconv.Atoi(v)).Ok() }) + assert.Equal(t, gust.Some[int](1), i.Next()) + assert.Equal(t, gust.Some[int](5), i.Next()) + assert.Equal(t, gust.None[int](), i.Next()) + } +} + +func TestFilterMap_2(t *testing.T) { + var c = make(chan string, 10) + for idx, i := range []iter.Iterator[string]{ + iter.FromElements("1", "two", "NaN", "four", "5"), + iter.FromChan(c), + } { + var i = i.ToInspect(func(v string) { + if idx == 0 { + c <- v + } + }).ToXFilterMap(func(v string) gust.Option[any] { return gust.Ret(strconv.Atoi(v)).Ok().ToX() }) + assert.Equal(t, gust.Some[any](1), i.Next()) + assert.Equal(t, gust.Some[any](5), i.Next()) + assert.Equal(t, gust.None[any](), i.Next()) + } +} + +func TestFilter(t *testing.T) { + var c = make(chan int, 10) + c <- 0 + c <- 1 + c <- 2 + close(c) + for _, i := range []iter.Iterator[int]{ + iter.FromElements(0, 1, 2), + iter.FromRange(0, 3), + iter.FromChan(c), + } { + var i = i.ToFilter(func(v int) bool { return v > 0 }) + assert.Equal(t, gust.Some(1), i.Next()) + assert.Equal(t, gust.Some(2), i.Next()) + assert.Equal(t, gust.None[int](), i.Next()) + } +} + +func TestFindMap(t *testing.T) { + var firstNumbe = iter.FromElements("lol", "NaN", "2", "5"). + XFindMap(func(s string) gust.Option[any] { + return gust.Ret(strconv.Atoi(s)).XOk() + }) + assert.Equal(t, gust.Some[any](int(2)), firstNumbe) +} + +func TestFind_1(t *testing.T) { + var a = []int8{1, 2, 3} + var i = iter.FromVec[int8](a) + assert.Equal(t, gust.Some[int8](2), i.Find(func(v int8) bool { + return v == 2 + })) + assert.Equal(t, gust.None[int8](), i.Find(func(v int8) bool { + return v == 5 + })) +} + +func TestFind_2(t *testing.T) { + var a = []int8{1, 2, 3} + var i = iter.FromVec[int8](a) + // / assert_eq!(iter.find(|&&x| x == 2), Some(&2)); + assert.Equal(t, gust.Some[int8](2), i.Find(func(v int8) bool { + return v == 2 + })) + // we can still use `iter`, as there are more elements. + assert.Equal(t, gust.Some[int8](3), i.Next()) +} + +func TestFlatMap(t *testing.T) { + var c = make(chan string, 10) + for _, i := range []iter.Iterator[string]{ + iter.FromElements("alpha", "beta", "gamma").ToInspect(func(v string) { + c <- v + }), + iter.FromChan(c), + } { + var merged = iter.ToFlatMap(i, func(t string) iter.Iterator[rune] { + return iter.FromString[rune](t) + }).Collect() + assert.Equal(t, "alphabetagamma", string(merged)) + } +} + +func TestFlatten(t *testing.T) { + var i = iter.FromElements( + iter.FromElements([]int{1, 2}, []int{3, 4}), + iter.FromElements([]int{5, 6}, []int{7, 8}), + ) + var d2 = iter.ToDeFlatten[iter.DeIterator[[]int], []int](i).Collect() + assert.Equal(t, [][]int{{1, 2}, {3, 4}, {5, 6}, {7, 8}}, d2) +} + +func TestFold_1(t *testing.T) { + var c = make(chan int8, 10) + for _, i := range []iter.Iterator[int8]{ + iter.FromElements[int8](1, 2, 3).ToInspect(func(v int8) { + c <- v + }), + iter.FromRange[int8](1, 3, true), + iter.FromChan(c), + } { + // the sum of all of the elements of the array + var sum = i.Fold(int8(0), func(acc any, v int8) any { + return acc.(int8) + v + }).(int8) + assert.Equal(t, int8(6), sum) + } +} + +func TestFold_2(t *testing.T) { + var c = make(chan int8, 10) + for _, i := range []iter.Iterator[int8]{ + iter.FromElements[int8](1, 2, 3, 4, 5).ToInspect(func(v int8) { + c <- v + }), + iter.FromRange[int8](1, 5, true), + iter.FromChan(c), + } { + var zero = "0" + var result = i.Fold(zero, func(acc any, v int8) any { + return fmt.Sprintf("(%s + %d)", acc.(string), v) + }).(string) + assert.Equal(t, "(((((0 + 1) + 2) + 3) + 4) + 5)", result) + } +} + +func TestFold_3(t *testing.T) { + var numbers = []int{1, 2, 3, 4, 5} + + // for loop: + var result = 0 + for _, x := range numbers { + result = result + x + } + + // fold: + var result2 = iter.FromVec(numbers).Fold(0, func(acc any, x int) any { + return acc.(int) + x + }).(int) + + // they're the same + assert.Equal(t, result, result2) +} + +func TestForEach_1(t *testing.T) { + var c = make(chan int, 5) + iter.FromRange(0, 5). + ToMap(func(i int) int { return i*2 + 1 }). + ForEach(func(i int) { + c <- i + }) + var v = iter.FromChan(c).Collect() + assert.Equal(t, []int{1, 3, 5, 7, 9}, v) +} + +func TestForEach_2(t *testing.T) { + var c = make(chan int) + go func() { + iter.FromRange(0, 5). + ToMap(func(i int) int { return i*2 + 1 }). + ForEach(func(i int) { + c <- i + }) + close(c) + }() + var v = iter.FromChan(c).Collect() + assert.Equal(t, []int{1, 3, 5, 7, 9}, v) +} + +var _ gust.Iterable[int] = (*Alternate)(nil) + +type Alternate struct { + state int +} + +func (a *Alternate) Next() gust.Option[int] { + var val = a.state + a.state = a.state + 1 + // if it's even, Some(i32), else None + if val%2 == 0 { + return gust.Some(val) + } + return gust.None[int]() +} + +func TestFuse(t *testing.T) { + var a = &Alternate{state: 0} + var i = iter.FromIterable[int](a) + // we can see our iterator going back and forth + assert.Equal(t, gust.Some(0), i.Next()) + assert.Equal(t, gust.None[int](), i.Next()) + assert.Equal(t, gust.Some(2), i.Next()) + assert.Equal(t, gust.None[int](), i.Next()) + // however, once we fuse it... + var j = i.ToFuse() + assert.Equal(t, gust.Some(4), j.Next()) + assert.Equal(t, gust.None[int](), j.Next()) + // it will always return `None` after the first time. + assert.Equal(t, gust.None[int](), j.Next()) + assert.Equal(t, gust.None[int](), j.Next()) + assert.Equal(t, gust.None[int](), j.Next()) + +} + +func TestInspect(t *testing.T) { + var numbers = iter.FromElements[string]("1", "2", "a", "3", "b"). + ToXMap(func(v string) any { + return gust.Ret(strconv.Atoi(v)) + }). + ToInspect(func(v any) { + v.(gust.Result[int]).InspectErr(func(err error) { + fmt.Println("Parsing error:", err) + }) + }). + ToFilterMap(func(v any) gust.Option[any] { + return v.(gust.Result[int]).Ok().ToX() + }). + Collect() + assert.Equal(t, []interface{}{1, 2, 3}, numbers) +} + +func TestIsPartitioned(t *testing.T) { + assert.True(t, iter.FromString[rune]("Iterator").IsPartitioned(func(r rune) bool { + return r >= 'A' && r <= 'Z' + })) + assert.False(t, iter.FromString[rune]("IntoIterator").IsPartitioned(func(r rune) bool { + return r >= 'A' && r <= 'Z' + })) +} + +func TestLast_1(t *testing.T) { + var a = []int{1, 2, 3} + var i = iter.FromVec(a) + assert.Equal(t, gust.Some(3), i.Last()) + assert.Equal(t, gust.None[int](), i.Last()) + assert.Equal(t, gust.None[int](), i.Next()) +} + +func TestLast_2(t *testing.T) { + var i = iter.FromRange(1, 3, true) + assert.Equal(t, gust.Some(3), i.Last()) + assert.Equal(t, gust.None[int](), i.Last()) + assert.Equal(t, gust.None[int](), i.Next()) +} + +func TestLast_3(t *testing.T) { + var c = make(chan int, 3) + c <- 1 + c <- 2 + c <- 3 + close(c) + var i = iter.FromChan(c) + assert.Equal(t, gust.Some(3), i.Last()) + assert.Equal(t, gust.None[int](), i.Last()) + assert.Equal(t, gust.None[int](), i.Next()) +} + +func TestIntersperse_1(t *testing.T) { + var c = make(chan int, 4) + c <- 0 + c <- 1 + c <- 2 + close(c) + for _, i := range []iter.Iterator[int]{ + iter.FromElements(0, 1, 2), + iter.FromRange(0, 3), + iter.FromChan(c), + } { + i := i.ToIntersperse(100) + assert.Equal(t, gust.Some(0), i.Next()) // The first element from `a`. + assert.Equal(t, gust.Some(100), i.Next()) // The separator. + assert.Equal(t, gust.Some(1), i.Next()) // The next element from `a`. + assert.Equal(t, gust.Some(100), i.Next()) // The separator. + assert.Equal(t, gust.Some(2), i.Next()) // The last element from `a`. + assert.Equal(t, gust.None[int](), i.Next()) // The iterator is finished. + + } +} + +func TestIntersperse_2(t *testing.T) { + var c = make(chan int, 4) + c <- 0 + c <- 1 + c <- 2 + close(c) + for _, i := range []iter.Iterator[int]{ + iter.FromElements(0, 1, 2), + iter.FromRange(0, 3), + iter.FromChan(c), + } { + i := i.ToPeekable().ToIntersperse(100) + assert.Equal(t, gust.Some(0), i.Next()) // The first element from `a`. + assert.Equal(t, gust.Some(100), i.Next()) // The separator. + assert.Equal(t, gust.Some(1), i.Next()) // The next element from `a`. + assert.Equal(t, gust.Some(100), i.Next()) // The separator. + assert.Equal(t, gust.Some(2), i.Next()) // The last element from `a`. + assert.Equal(t, gust.None[int](), i.Next()) // The iterator is finished. + } +} + +func TestIntersperse_3(t *testing.T) { + var c = make(chan int, 4) + c <- 0 + c <- 1 + c <- 2 + close(c) + for _, i := range []iter.Iterator[int]{ + iter.FromElements(0, 1, 2), + iter.FromRange(0, 3), + iter.FromChan(c), + } { + i := i.ToIntersperseWith(func() int { return 100 }) + assert.Equal(t, gust.Some(0), i.Next()) // The first element from `a`. + assert.Equal(t, gust.Some(100), i.Next()) // The separator. + assert.Equal(t, gust.Some(1), i.Next()) // The next element from `a`. + assert.Equal(t, gust.Some(100), i.Next()) // The separator. + assert.Equal(t, gust.Some(2), i.Next()) // The last element from `a`. + assert.Equal(t, gust.None[int](), i.Next()) // The iterator is finished. + } +} + +func TestMap_1(t *testing.T) { + var c = make(chan int, 4) + c <- 1 + c <- 2 + c <- 3 + close(c) + for _, i := range []iter.Iterator[int]{ + iter.FromElements(1, 2, 3), + iter.FromRange(1, 4), + iter.FromChan(c), + } { + i := i.ToMap(func(v int) int { return v * 2 }) + assert.Equal(t, gust.Some(2), i.Next()) + assert.Equal(t, gust.Some(4), i.Next()) + assert.Equal(t, gust.Some(6), i.Next()) + assert.Equal(t, gust.None[int](), i.Next()) + } +} + +func TestMap_2(t *testing.T) { + var c = make(chan int, 4) + c <- 1 + c <- 2 + c <- 3 + close(c) + for _, i := range []iter.Iterator[int]{ + iter.FromElements(1, 2, 3), + iter.FromRange(1, 4), + iter.FromChan(c), + } { + i := i.ToXMap(func(v int) any { return fmt.Sprintf("%d", v*2) }) + assert.Equal(t, gust.Some[any]("2"), i.Next()) + assert.Equal(t, gust.Some[any]("4"), i.Next()) + assert.Equal(t, gust.Some[any]("6"), i.Next()) + assert.Equal(t, gust.None[any](), i.Next()) + } +} + +func TestMap_3(t *testing.T) { + var c = make(chan int, 4) + c <- 1 + c <- 2 + c <- 3 + close(c) + for _, i := range []iter.Iterator[int]{ + iter.FromElements(1, 2, 3), + iter.FromRange(1, 4), + iter.FromChan(c), + } { + i := iter.ToMap(i, func(v int) string { return fmt.Sprintf("%d", v*2) }) + assert.Equal(t, gust.Some[string]("2"), i.Next()) + assert.Equal(t, gust.Some[string]("4"), i.Next()) + assert.Equal(t, gust.Some[string]("6"), i.Next()) + assert.Equal(t, gust.None[string](), i.Next()) + } +} + +func TestMapWhile_1(t *testing.T) { + var c = make(chan int, 10) + for _, i := range []iter.Iterator[int]{ + iter.FromElements(-1, 4, 0, 1).ToInspect(func(v int) { + c <- v + }), + iter.FromChan(c), + } { + i := i.ToMapWhile(func(x int) gust.Option[int] { return checkedDivide(16, x) }) + assert.Equal(t, gust.Some(-16), i.Next()) + assert.Equal(t, gust.Some(4), i.Next()) + assert.Equal(t, gust.None[int](), i.Next()) + assert.Equal(t, gust.Some(16), i.Next()) + } +} + +func checkedDivide(x, y int) gust.Option[int] { + if y == 0 { + return gust.None[int]() + } + return gust.Some(x / y) +} + +func TestMapWhile_2(t *testing.T) { + var c = make(chan int, 10) + for _, i := range []iter.Iterator[int]{ + iter.FromElements(1, 2, -3, 4).ToInspect(func(v int) { + c <- v + }), + iter.FromChan(c), + } { + a := i.ToXMapWhile(func(x int) gust.Option[any] { + if x < 0 { + return gust.None[any]() + } + return gust.Some[any](uint(x)) + }).Collect() + assert.Equal(t, []any{uint(1), uint(2)}, a) + } +} + func TestNextChunk(t *testing.T) { - var iter = FromVec([]int{1, 2, 3}) + var iter = iter.FromVec([]int{1, 2, 3}) assert.Equal(t, []int{1, 2}, iter.NextChunk(2).Unwrap()) assert.Equal(t, []int{3}, iter.NextChunk(2).UnwrapErr()) assert.Equal(t, []int{}, iter.NextChunk(2).UnwrapErr()) } -func TestZip(t *testing.T) { - var a = FromVec([]string{"x", "y", "z"}) - var b = FromVec([]int{1, 2}) - var iter = ToZip[string, int](a, b) - var pairs = Fold[gust.Pair[string, int]](iter, nil, func(acc []gust.Pair[string, int], t gust.Pair[string, int]) []gust.Pair[string, int] { +func TestNextChunk_1(t *testing.T) { + var i = iter.FromString[rune]("中国-CN") + assert.Equal(t, []rune{'中', '国'}, i.NextChunk(2).Unwrap()) + assert.Equal(t, []rune{'-', 'C'}, i.NextChunk(2).Unwrap()) + assert.Equal(t, []rune{'N'}, i.NextChunk(4).UnwrapErr()) + assert.Equal(t, []rune{}, i.NextChunk(1).UnwrapErr()) + assert.Equal(t, []rune{}, i.NextChunk(0).Unwrap()) +} + +func TestNextChunk_2(t *testing.T) { + var i = iter.FromString[byte]("中国-CN") + assert.Equal(t, []byte{0xe4, 0xb8, 0xad}, i.NextChunk(3).Unwrap()) // '中' + assert.Equal(t, []byte{0xe5, 0x9b, 0xbd}, i.NextChunk(3).Unwrap()) // '国' + assert.Equal(t, []byte{'-'}, i.NextChunk(1).Unwrap()) + assert.Equal(t, []byte{'C'}, i.NextChunk(1).Unwrap()) + assert.Equal(t, []byte{'N'}, i.NextChunk(3).UnwrapErr()) + assert.Equal(t, []byte{}, i.NextChunk(1).UnwrapErr()) + assert.Equal(t, []byte{}, i.NextChunk(0).Unwrap()) +} + +func TestNext_1(t *testing.T) { + var a = []int{1, 2, 3} + var i = iter.FromVec(a) + // A call to Next() returns the next value... + assert.Equal(t, gust.Some(1), i.Next()) + assert.Equal(t, gust.Some(2), i.Next()) + assert.Equal(t, gust.Some(3), i.Next()) + // ... and then None once it's over. + assert.Equal(t, gust.None[int](), i.Next()) + // More calls may or may not return `None`. Here, they always will. + assert.Equal(t, gust.None[int](), i.Next()) + assert.Equal(t, gust.None[int](), i.Next()) +} + +func TestNext_2(t *testing.T) { + var i = iter.FromRange(1, 3, true) + // A call to Next() returns the next value... + assert.Equal(t, gust.Some(1), i.Next()) + assert.Equal(t, gust.Some(2), i.Next()) + assert.Equal(t, gust.Some(3), i.Next()) + // ... and then None once it's over. + assert.Equal(t, gust.None[int](), i.Next()) + // More calls may or may not return `None`. Here, they always will. + assert.Equal(t, gust.None[int](), i.Next()) + assert.Equal(t, gust.None[int](), i.Next()) +} + +func TestNext_3(t *testing.T) { + var c = make(chan int, 3) + c <- 1 + c <- 2 + c <- 3 + close(c) + var i = iter.FromChan(c) + // A call to Next() returns the next value... + assert.Equal(t, gust.Some(1), i.Next()) + assert.Equal(t, gust.Some(2), i.Next()) + assert.Equal(t, gust.Some(3), i.Next()) + // ... and then None once it's over. + assert.Equal(t, gust.None[int](), i.Next()) + // More calls may or may not return `None`. Here, they always will. + assert.Equal(t, gust.None[int](), i.Next()) + assert.Equal(t, gust.None[int](), i.Next()) +} + +func TestNth(t *testing.T) { + var c = make(chan int, 4) + c <- 1 + c <- 2 + c <- 3 + close(c) + for _, i := range []iter.Iterator[int]{ + iter.FromElements(1, 2, 3), + iter.FromRange(1, 4), + iter.FromChan(c), + } { + assert.Equal(t, gust.Some(2), i.Nth(1)) + // Calling `Nth()` multiple times doesn't rewind the iterator: + assert.Equal(t, gust.None[int](), i.Nth(1)) + // Returning `None` if there are less than `n + 1` elements: + assert.Equal(t, gust.None[int](), i.Nth(10)) + } +} + +func TestPartition(t *testing.T) { + var c = make(chan int, 10) + for _, i := range []iter.Iterator[int]{ + iter.FromElements(1, 2, 3).ToInspect(func(v int) { + c <- v + }), + iter.FromRange(1, 4), + iter.FromChan(c), + } { + var even, odd = i.Partition(func(x int) bool { return x%2 == 0 }) + assert.Equal(t, []int{2}, even) + assert.Equal(t, []int{1, 3}, odd) + } +} + +func TestPeekable(t *testing.T) { + var i = iter.FromElements(1, 2, 3).ToPeekable() + assert.Equal(t, gust.Some(1), i.Peek()) + assert.Equal(t, gust.Some(1), i.Peek()) + assert.Equal(t, gust.Some(1), i.Next()) + peeked := i.Peek() + if peeked.IsSome() { + p := peeked.GetOrInsertWith(nil) + assert.Equal(t, 2, *p) + *p = 1000 + } + // The value reappears as the iterator continues + assert.Equal(t, []int{1000, 3}, i.Collect()) +} + +func TestPosition_1(t *testing.T) { + var a = []int8{1, 2, 3} + assert.Equal(t, gust.Some(1), iter.FromVec[int8](a).Position(func(v int8) bool { + return v == 2 + })) + assert.Equal(t, gust.None[int](), iter.FromVec[int8](a).Position(func(v int8) bool { + return v == 5 + })) +} + +func TestPosition_2(t *testing.T) { + // Stopping at the first `true`: + var a = iter.FromElements(1, 2, 3, 4) + assert.Equal(t, gust.Some(1), a.Position(func(v int) bool { + return v >= 2 + })) + // we can still use `iter`, as there are more elements. + assert.Equal(t, gust.Some(3), a.Next()) + // The returned index depends on iterator state + assert.Equal(t, gust.Some(0), a.Position(func(v int) bool { + return v == 4 + })) +} + +func findMax[T gust.Integer](i iter.Iterator[T]) gust.Option[T] { + return i.Reduce(func(acc T, v T) T { + if acc >= v { + return acc + } + return v + }) +} + +func TestReduce(t *testing.T) { + var a = []int{10, 20, 5, -23, 0} + var b []uint + assert.Equal(t, gust.Some(20), findMax[int](iter.FromVec(a))) + assert.Equal(t, gust.None[uint](), findMax[uint](iter.FromVec(b))) +} + +func TestRev(t *testing.T) { + for _, i := range []iter.DeIterator[int]{ + iter.FromElements(1, 2, 3), + iter.FromRange(1, 3, true), + } { + var rev = i.ToRev() + assert.Equal(t, gust.Some(3), rev.Next()) + assert.Equal(t, gust.Some(2), rev.Next()) + assert.Equal(t, gust.Some(1), rev.Next()) + assert.Equal(t, gust.None[int](), rev.Next()) + } +} + +func TestRposition_1(t *testing.T) { + var a = []int8{1, 2, 3} + assert.Equal(t, gust.Some(2), iter.FromVec[int8](a).Rposition(func(v int8) bool { + return v == 3 + })) + assert.Equal(t, gust.None[int](), iter.FromVec[int8](a).Rposition(func(v int8) bool { + return v == 5 + })) +} + +func TestRposition_2(t *testing.T) { + var a = iter.FromElements(1, 2, 3) + assert.Equal(t, gust.Some(1), a.Rposition(func(v int) bool { + return v == 2 + })) + assert.Equal(t, gust.Some(1), a.Next()) +} + +func TestScan(t *testing.T) { + var c = make(chan int, 10) + for _, i := range []iter.Iterator[int]{ + iter.FromElements(1, 2, 3).ToInspect(func(v int) { + c <- v + }), + iter.FromRange(1, 4), + iter.FromChan(c), + } { + j := i.ToScan(1, func(state *any, x int) gust.Option[any] { + // each iteration, we'll multiply the state by the element + *state = (*state).(int) * x + // then, we'll yield the negation of the state + return gust.Some[any](-(*state).(int)) + }) + assert.Equal(t, gust.Some[any](-1), j.Next()) + assert.Equal(t, gust.Some[any](-2), j.Next()) + assert.Equal(t, gust.Some[any](-6), j.Next()) + assert.Equal(t, gust.None[any](), j.Next()) + } +} + +func TestSizeHint_1(t *testing.T) { + var i = iter.FromElements(1, 2, 3) + var lo, hi = i.SizeHint() + assert.Equal(t, uint(3), lo) + assert.Equal(t, gust.Some[uint](3), hi) + _ = i.Next() + lo, hi = i.SizeHint() + assert.Equal(t, uint(2), lo) + assert.Equal(t, gust.Some[uint](2), hi) +} + +func TestSizeHint_2(t *testing.T) { + var i = iter.FromRange(1, 3, true) + var lo, hi = i.SizeHint() + assert.Equal(t, uint(3), lo) + assert.Equal(t, gust.Some[uint](3), hi) + _ = i.Next() + lo, hi = i.SizeHint() + assert.Equal(t, uint(2), lo) + assert.Equal(t, gust.Some[uint](2), hi) +} + +func TestSizeHint_3(t *testing.T) { + var c = make(chan int, 3) + c <- 1 + c <- 2 + c <- 3 + var i = iter.FromChan(c) + var lo, hi = i.SizeHint() + assert.Equal(t, uint(3), lo) + assert.Equal(t, gust.Some[uint](3), hi) + _ = i.Next() + lo, hi = i.SizeHint() + assert.Equal(t, uint(2), lo) + assert.Equal(t, gust.Some[uint](3), hi) +} + +func TestSkip(t *testing.T) { + var c = make(chan int, 10) + for _, i := range []iter.Iterator[int]{ + iter.FromElements(1, 2, 3).ToInspect(func(v int) { + c <- v + }), + iter.FromRange(1, 4), + iter.FromChan(c), + } { + var iter = i.ToSkip(2) + assert.Equal(t, gust.Some(3), iter.Next()) + assert.Equal(t, gust.None[int](), iter.Next()) + } +} + +func TestSkipWhile(t *testing.T) { + var c = make(chan int, 10) + for _, i := range []iter.Iterator[int]{ + iter.FromElements(-1, 0, 1).ToInspect(func(v int) { + c <- v + }), + iter.FromRange(-1, 2), + iter.FromChan(c), + } { + var iter = i.ToSkipWhile(func(v int) bool { + return v < 0 + }) + assert.Equal(t, gust.Some(0), iter.Next()) + assert.Equal(t, gust.Some(1), iter.Next()) + assert.Equal(t, gust.None[int](), iter.Next()) + } +} + +func TestStepBy(t *testing.T) { + var c = make(chan int, 6) + c <- 0 + c <- 1 + c <- 2 + c <- 3 + c <- 4 + c <- 5 + close(c) + for _, i := range []iter.Iterator[int]{ + iter.FromElements(0, 1, 2, 3, 4, 5), + iter.FromRange(0, 5, true), + iter.FromChan(c), + } { + var stepBy = i.ToStepBy(2) + assert.Equal(t, gust.Some(0), stepBy.Next()) + assert.Equal(t, gust.Some(2), stepBy.Next()) + assert.Equal(t, gust.Some(4), stepBy.Next()) + assert.Equal(t, gust.None[int](), stepBy.Next()) + } +} + +func TestTake(t *testing.T) { + var c = make(chan int, 10) + for _, i := range []iter.Iterator[int]{ + iter.FromElements(1, 2, 3).ToInspect(func(v int) { + c <- v + }), + iter.FromRange(1, 4), + iter.FromChan(c), + } { + var iter = i.ToTake(2) + assert.Equal(t, gust.Some(1), iter.Next()) + assert.Equal(t, gust.Some(2), iter.Next()) + assert.Equal(t, gust.None[int](), iter.Next()) + } +} + +func TestTakeWhile(t *testing.T) { + var c = make(chan int, 10) + for _, i := range []iter.Iterator[int]{ + iter.FromElements(-1, 0, 1).ToInspect(func(v int) { + c <- v + }), + iter.FromRange(-1, 2), + iter.FromChan(c), + } { + var iter = i.ToTakeWhile(func(v int) bool { + return v < 0 + }) + assert.Equal(t, gust.Some(-1), iter.Next()) + assert.Equal(t, gust.None[int](), iter.Next()) + } +} + +func TestTryFind(t *testing.T) { + var a = []string{"1", "2", "lol", "NaN", "5"} + var isMyNum = func(s string, search int) gust.Result[bool] { + return ret.Map[int, bool](gust.Ret(strconv.Atoi(s)), func(x int) bool { + return x == search + }) + } + var result = iter.FromVec[string](a).TryFind(func(s string) gust.Result[bool] { + return isMyNum(s, 2) + }) + assert.Equal(t, gust.Ok(gust.Some[string]("2")), result) + result = iter.FromVec[string](a).TryFind(func(s string) gust.Result[bool] { + return isMyNum(s, 5) + }) + assert.True(t, result.IsErr()) +} + +func TestTryFold_1(t *testing.T) { + var c = make(chan int8, 10) + for _, i := range []iter.Iterator[int8]{ + iter.FromElements[int8](1, 2, 3).ToInspect(func(v int8) { + c <- v + }), + iter.FromRange[int8](1, 4), + iter.FromChan(c), + } { + // the checked sum of all the elements of the array + var sum = i.TryFold(int8(0), func(acc any, v int8) gust.AnyCtrlFlow { + return digit.CheckedAdd[int8](acc.(int8), v).CtrlFlow().ToX() + }) + assert.Equal(t, gust.AnyContinue(int8(6)), sum) + } +} + +func TestTryFold_2(t *testing.T) { + var i = iter.FromElements[int8](10, 20, 30, 100, 40, 50) + // This sum overflows when adding the 100 element + var sum = i.TryFold(int8(0), func(acc any, v int8) gust.AnyCtrlFlow { + return digit.CheckedAdd[int8](acc.(int8), v).CtrlFlow().ToX() + }) + assert.Equal(t, gust.AnyBreak(gust.Void(nil)), sum) + // Because it short-circuited, the remaining elements are still + // available through the iterator. + assert.Equal(t, uint(2), i.Remaining()) + assert.Equal(t, gust.Some[int8](40), i.Next()) +} + +func TestTryFold_3(t *testing.T) { + var triangular8 = iter.FromRange[int8](1, 30).TryFold(int8(0), func(acc any, v int8) gust.AnyCtrlFlow { + return digit.CheckedAdd[int8](acc.(int8), v).XMapOrElse( + func() any { + return gust.AnyBreak(acc) + }, func(sum int8) any { + return gust.AnyContinue(sum) + }).(gust.AnyCtrlFlow) + }) + assert.Equal(t, gust.AnyBreak(int8(120)), triangular8) + + var triangular64 = iter.FromRange[uint64](1, 30).TryFold(uint64(0), func(acc any, v uint64) gust.AnyCtrlFlow { + return digit.CheckedAdd(acc.(uint64), v).XMapOrElse( + func() any { + return gust.AnyBreak(acc) + }, func(sum uint64) any { + return gust.AnyContinue(sum) + }).(gust.AnyCtrlFlow) + }) + assert.Equal(t, gust.AnyContinue(uint64(435)), triangular64) +} + +func TestTryForEach(t *testing.T) { + var c = make(chan int, 1000) + for _, i := range []iter.Iterator[int]{ + iter.FromRange[int](2, 100).ToInspect(func(v int) { + c <- v + }), + iter.FromChan(c), + } { + var r = i.TryForEach(func(v int) gust.AnyCtrlFlow { + if 323%v == 0 { + return gust.AnyBreak(v) + } + return gust.AnyContinue(nil) + }) + assert.Equal(t, gust.AnyBreak(17), r) + } +} + +func TestTryReduce_1(t *testing.T) { + // Safely calculate the sum of a series of numbers: + var numbers = []uint{10, 20, 5, 23, 0} + var sum = iter.FromVec(numbers).TryReduce(func(x, y uint) gust.Result[uint] { + return digit.CheckedAdd(x, y).OkOr("overflow") + }) + assert.Equal(t, gust.Ok(gust.Some[uint](58)), sum) +} + +func TestTryReduce_2(t *testing.T) { + // Determine when a reduction short circuited: + var numbers = []uint{1, 2, 3, ^uint(0), 4, 5} + var sum = iter.FromVec(numbers).TryReduce(func(x, y uint) gust.Result[uint] { + return digit.CheckedAdd(x, y).OkOr("overflow") + }) + assert.Equal(t, gust.Err[gust.Option[uint]]("overflow"), sum) +} + +func TestTryReduce_3(t *testing.T) { + // Determine when a reduction was not performed because there are no elements: + var numbers = []uint{} + var sum = iter.FromVec(numbers).TryReduce(func(x, y uint) gust.Result[uint] { + return digit.CheckedAdd(x, y).OkOr("overflow") + }) + assert.Equal(t, gust.Ok(gust.None[uint]()), sum) +} + +func TestZip_1(t *testing.T) { + var a = iter.FromVec([]string{"x", "y", "z"}) + var b = iter.FromVec([]int{1, 2}) + var i = iter.ToZip[string, int](a, b) + var pairs = iter.Fold[gust.Pair[string, int]](i, nil, func(acc []gust.Pair[string, int], t gust.Pair[string, int]) []gust.Pair[string, int] { return append(acc, t) }) assert.Equal(t, []gust.Pair[string, int]{{A: "x", B: 1}, {A: "y", B: 2}}, pairs) } +func TestZip_2(t *testing.T) { + var c = make(chan int, 3) + c <- 4 + c <- 5 + c <- 6 + close(c) + for _, x := range [][2]iter.Iterator[int]{ + {iter.FromElements(1, 2, 3), iter.FromElements(4, 5, 6)}, + {iter.FromRange(1, 4), iter.FromChan(c)}, + } { + var i = iter.ToZip(x[0], x[1]) + assert.Equal(t, gust.Some(gust.Pair[int, int]{A: 1, B: 4}), i.Next()) + assert.Equal(t, gust.Some(gust.Pair[int, int]{A: 2, B: 5}), i.Next()) + assert.Equal(t, gust.Some(gust.Pair[int, int]{A: 3, B: 6}), i.Next()) + assert.Equal(t, gust.None[gust.Pair[int, int]](), i.Next()) + } +} + func TestToUnique(t *testing.T) { - var data = FromElements(10, 20, 30, 20, 40, 10, 50) - assert.Equal(t, []int{10, 20, 30, 40, 50}, ToUnique[int](data).Collect()) + var data = iter.FromElements(10, 20, 30, 20, 40, 10, 50) + assert.Equal(t, []int{10, 20, 30, 40, 50}, iter.ToUnique[int](data).Collect()) } func TestToDeUnique(t *testing.T) { - var data = FromElements(10, 20, 30, 20, 40, 10, 50) - assert.Equal(t, []int{10, 20, 30, 40, 50}, ToDeUnique[int](data).Collect()) - var data2 = FromElements(10, 20, 30, 20, 40, 10, 50) - assert.Equal(t, []int{50, 10, 40, 20, 30}, ToDeUnique[int](data2).ToRev().Collect()) - var data3 = FromElements(10, 20, 30, 20, 40, 10, 50) - assert.Equal(t, []int{50, 10, 40, 20, 30}, ToDeUnique(data3.ToRev()).Collect()) + var data = iter.FromElements(10, 20, 30, 20, 40, 10, 50) + assert.Equal(t, []int{10, 20, 30, 40, 50}, iter.ToDeUnique[int](data).Collect()) + var data2 = iter.FromElements(10, 20, 30, 20, 40, 10, 50) + assert.Equal(t, []int{50, 10, 40, 20, 30}, iter.ToDeUnique[int](data2).ToRev().Collect()) + var data3 = iter.FromElements(10, 20, 30, 20, 40, 10, 50) + assert.Equal(t, []int{50, 10, 40, 20, 30}, iter.ToDeUnique(data3.ToRev()).Collect()) } func TestToUniqueBy(t *testing.T) { - var data = FromElements("a", "bb", "aa", "c", "ccc") - assert.Equal(t, []string{"a", "bb", "ccc"}, ToUniqueBy[string, int](data, func(s string) int { return len(s) }).Collect()) + var data = iter.FromElements("a", "bb", "aa", "c", "ccc") + assert.Equal(t, []string{"a", "bb", "ccc"}, iter.ToUniqueBy[string, int](data, func(s string) int { return len(s) }).Collect()) } func TestToDeUniqueBy(t *testing.T) { var f = func(s string) int { return len(s) } - var data = FromElements("a", "bb", "aa", "c", "ccc") - assert.Equal(t, []string{"a", "bb", "ccc"}, ToDeUniqueBy[string, int](data, f).Collect()) - var data2 = FromElements("a", "bb", "aa", "c", "ccc") - assert.Equal(t, []string{"ccc", "c", "aa"}, ToDeUniqueBy[string, int](data2, f).ToRev().Collect()) - var data3 = FromElements("a", "bb", "aa", "c", "ccc") - assert.Equal(t, []string{"ccc", "c", "aa"}, ToDeUniqueBy[string, int](data3.ToRev(), f).Collect()) + var data = iter.FromElements("a", "bb", "aa", "c", "ccc") + assert.Equal(t, []string{"a", "bb", "ccc"}, iter.ToDeUniqueBy[string, int](data, f).Collect()) + var data2 = iter.FromElements("a", "bb", "aa", "c", "ccc") + assert.Equal(t, []string{"ccc", "c", "aa"}, iter.ToDeUniqueBy[string, int](data2, f).ToRev().Collect()) + var data3 = iter.FromElements("a", "bb", "aa", "c", "ccc") + assert.Equal(t, []string{"ccc", "c", "aa"}, iter.ToDeUniqueBy[string, int](data3.ToRev(), f).Collect()) } diff --git a/examples/iterator/iter_overview_test.go b/iter/overview_test.go similarity index 90% rename from examples/iterator/iter_overview_test.go rename to iter/overview_test.go index 45d6498..93af65c 100644 --- a/examples/iterator/iter_overview_test.go +++ b/iter/overview_test.go @@ -1,4 +1,4 @@ -package iterator_test +package iter_test import ( "fmt" diff --git a/opt/option_test.go b/opt/option_test.go new file mode 100644 index 0000000..4da4c54 --- /dev/null +++ b/opt/option_test.go @@ -0,0 +1,96 @@ +package opt_test + +import ( + "math" + "strconv" + "testing" + + "github.com/andeya/gust" + "github.com/andeya/gust/opt" + "github.com/stretchr/testify/assert" +) + +func TestOption_AndThen_1(t *testing.T) { + var sqThenToString = func(x uint32) gust.Option[string] { + if x <= math.MaxUint32/x { + return gust.Some(strconv.FormatUint(uint64(x*x), 10)) + } + return gust.None[string]() + } + assert.Equal(t, gust.Some("4"), opt.AndThen(gust.Some[uint32](2), sqThenToString)) + assert.Equal(t, gust.None[string](), opt.AndThen(gust.Some[uint32](1000000), sqThenToString)) + assert.Equal(t, gust.None[string](), opt.AndThen(gust.None[uint32](), sqThenToString)) +} + +func TestOption_Contains(t *testing.T) { + { + var x = gust.Some(2) + assert.Equal(t, true, opt.Contains(x, 2)) + } + { + var x = gust.Some(3) + assert.Equal(t, false, opt.Contains(x, 2)) + } + { + var x = gust.None[int]() + assert.Equal(t, false, opt.Contains(x, 2)) + } +} + +func TestOption_MapOrElse_1(t *testing.T) { + var k = 21 + { + var x = gust.Some("foo") + assert.Equal(t, 3, opt.MapOrElse(x, func() int { return 2 * k }, func(v string) int { return len(v) })) + } + { + var x gust.Option[string] + assert.Equal(t, 42, opt.MapOrElse(x, func() int { return 2 * k }, func(v string) int { return len(v) })) + } +} + +func TestOption_MapOr_1(t *testing.T) { + { + var x = gust.Some("foo") + assert.Equal(t, 3, opt.MapOr(x, 42, func(v string) int { return len(v) })) + } + { + var x gust.Option[string] + assert.Equal(t, 42, opt.MapOr(x, 42, func(v string) int { return len(v) })) + } +} + +func TestOption_Map_1(t *testing.T) { + var maybeSomeString = gust.Some("Hello, World!") + var maybeSomeLen = opt.Map(maybeSomeString, func(s string) int { return len(s) }) + assert.Equal(t, maybeSomeLen, gust.Some(13)) +} + +func TestOption_Unzip(t *testing.T) { + var x = gust.Some[gust.Pair[int, string]](gust.Pair[int, string]{A: 1, B: "hi"}) + var y = gust.None[gust.Pair[int, string]]() + assert.Equal(t, opt.Unzip(x), gust.Pair[gust.Option[int], gust.Option[string]]{A: gust.Some[int](1), B: gust.Some[string]("hi")}) + assert.Equal(t, opt.Unzip(y), gust.Pair[gust.Option[int], gust.Option[string]]{A: gust.None[int](), B: gust.None[string]()}) +} + +func TestOption_Zip(t *testing.T) { + var x = gust.Some[byte](1) + var y = gust.Some("hi") + var z = gust.None[byte]() + assert.Equal(t, gust.Some(gust.Pair[byte, string]{1, "hi"}), opt.Zip(x, y)) + assert.Equal(t, gust.None[gust.Pair[byte, byte]](), opt.Zip(x, z)) +} + +func TestOption_ZipWith(t *testing.T) { + type Point struct { + x float64 + y float64 + } + var newPoint = func(x float64, y float64) Point { + return Point{x, y} + } + var x = gust.Some(17.5) + var y = gust.Some(42.7) + assert.Equal(t, opt.ZipWith(x, y, newPoint), gust.Some(Point{x: 17.5, y: 42.7})) + assert.Equal(t, opt.ZipWith(x, gust.None[float64](), newPoint), gust.None[Point]()) +} diff --git a/option_test.go b/option_test.go index 824ee58..fc6613a 100644 --- a/option_test.go +++ b/option_test.go @@ -2,12 +2,92 @@ package gust_test import ( "encoding/json" + "fmt" + "math" + "strconv" "testing" + "time" "github.com/andeya/gust" + "github.com/andeya/gust/opt" + "github.com/andeya/gust/valconv" "github.com/stretchr/testify/assert" ) +func ExampleOption() { + type A struct { + X int + } + var a = gust.Some(A{X: 1}) + fmt.Println(a.IsSome(), a.IsNone()) + + var b = gust.None[A]() + fmt.Println(b.IsSome(), b.IsNone()) + + var x = b.UnwrapOr(A{X: 2}) + fmt.Println(x) + + var c *A + fmt.Println(gust.PtrOpt(c).IsNone()) + fmt.Println(gust.ElemOpt(c).IsNone()) + c = new(A) + fmt.Println(gust.PtrOpt(c).IsNone()) + fmt.Println(gust.ElemOpt(c).IsNone()) + + type B struct { + Y string + } + var d = opt.Map(a, func(t A) B { + return B{ + Y: strconv.Itoa(t.X), + } + }) + fmt.Println(d) + + // Output: + // true false + // false true + // {2} + // true + // true + // false + // false + // Some({1}) +} + +func ExampleOption_Inspect() { + // prints "got: 3" + _ = gust.Some(3).Inspect(func(x int) { + fmt.Println("got:", x) + }) + + // prints nothing + _ = gust.None[int]().Inspect(func(x int) { + fmt.Println("got:", x) + }) + + // Output: + // got: 3 +} + +func TestOption(t *testing.T) { + var divide = func(numerator, denominator float64) gust.Option[float64] { + if denominator == 0.0 { + return gust.None[float64]() + } + return gust.Some(numerator / denominator) + } + // The return value of the function is an option + divide(2.0, 3.0). + Inspect(func(x float64) { + // Pattern match to retrieve the value + t.Log("Result:", x) + }). + InspectNone(func() { + t.Log("Cannot divide by 0") + }) +} + func TestOptionJSON(t *testing.T) { var r = gust.None[any]() var b, err = json.Marshal(r) @@ -64,3 +144,334 @@ func TestOptionJSON2(t *testing.T) { assert.NoError(t, err6) assert.Equal(t, r5, r6) } + +func TestOption_And_1(t *testing.T) { + { + var x = gust.Some[uint32](2) + var y gust.Option[uint32] + assert.Equal(t, gust.None[uint32](), x.And(y)) + } + { + var x gust.Option[uint32] + var y = gust.Some[uint32](3) + assert.Equal(t, gust.None[uint32](), x.And(y)) + } + { + var x = gust.Some[uint32](2) + var y = gust.Some[uint32](3) + assert.Equal(t, gust.Some[uint32](3), x.And(y)) + } + { + var x gust.Option[uint32] + var y gust.Option[uint32] + assert.Equal(t, gust.None[uint32](), x.And(y)) + } +} + +func TestOption_And_2(t *testing.T) { + { + var x = gust.Some[uint32](2) + var y gust.Option[string] + assert.Equal(t, gust.None[string]().ToX(), x.XAnd(y.ToX())) + } + { + var x gust.Option[uint32] + var y = gust.Some[string]("foo") + assert.Equal(t, gust.None[string]().ToX(), x.XAnd(y.ToX())) + } + { + var x = gust.Some[uint32](2) + var y = gust.Some[string]("foo") + assert.Equal(t, gust.Some[string]("foo").ToX(), x.XAnd(y.ToX())) + } + { + var x gust.Option[uint32] + var y gust.Option[string] + assert.Equal(t, gust.None[string]().ToX(), x.XAnd(y.ToX())) + } +} + +func TestOption_AndThen_2(t *testing.T) { + var sqThenToString = func(x uint32) gust.Option[any] { + if x <= math.MaxUint32/x { + return gust.Some[any](strconv.FormatUint(uint64(x*x), 10)) + } + return gust.None[any]() + } + assert.Equal(t, gust.Some("4").ToX(), gust.Some[uint32](2).XAndThen(sqThenToString)) + assert.Equal(t, gust.None[string]().ToX(), gust.Some[uint32](1000000).XAndThen(sqThenToString)) + assert.Equal(t, gust.None[string]().ToX(), gust.None[uint32]().XAndThen(sqThenToString)) +} + +func TestOption_Expect(t *testing.T) { + { + var x = gust.Some("value") + assert.Equal(t, "value", x.Expect("fruits are healthy")) + } + defer func() { + assert.Equal(t, gust.ToErrBox("fruits are healthy 1"), recover()) + defer func() { + assert.Equal(t, gust.ToErrBox("fruits are healthy 2"), recover()) + }() + var x gust.Option[string] + x.Expect("fruits are healthy 2") // panics with `fruits are healthy 2` + }() + var x = gust.None[string]() + x.Expect("fruits are healthy 1") // panics with `fruits are healthy 1` +} + +func TestOption_Filter(t *testing.T) { + var isEven = func(n int32) bool { + return n%2 == 0 + } + assert.Equal(t, gust.None[int32](), gust.None[int32]().Filter(isEven)) + assert.Equal(t, gust.None[int32](), gust.Some[int32](3).Filter(isEven)) + assert.Equal(t, gust.Some[int32](4), gust.Some[int32](4).Filter(isEven)) +} + +func TestOption_GetOrInsertDefault(t *testing.T) { + none := gust.None[int]() + assert.Equal(t, valconv.Ref(0), none.GetOrInsertDefault()) + assert.Equal(t, valconv.Ref(0), none.AsPtr()) + some := gust.Some[int](1) + assert.Equal(t, valconv.Ref(1), some.GetOrInsertDefault()) + assert.Equal(t, valconv.Ref(1), some.AsPtr()) +} + +func TestOption_GetOrInsert(t *testing.T) { + var x = gust.None[int]() + var y = x.GetOrInsert(5) + assert.Equal(t, 5, *y) + *y = 7 + assert.Equal(t, 7, x.Unwrap()) +} + +func TestOption_GetOrInsertWith(t *testing.T) { + var x = gust.None[int]() + var y = x.GetOrInsertWith(func() int { return 5 }) + assert.Equal(t, 5, *y) + assert.Equal(t, 5, x.Unwrap()) + *y = 7 + assert.Equal(t, 7, x.Unwrap()) + + var x2 = gust.None[int]() + var y2 = x2.GetOrInsertWith(nil) + assert.Equal(t, 0, *y2) + assert.Equal(t, 0, x2.Unwrap()) + *y2 = 7 + assert.Equal(t, 7, x2.Unwrap()) +} + +func TestOption_Insert(t *testing.T) { + var opt = gust.None[int]() + var val = opt.Insert(1) + assert.Equal(t, 1, *val) + assert.Equal(t, 1, opt.Unwrap()) + val = opt.Insert(2) + assert.Equal(t, 2, *val) + *val = 3 + assert.Equal(t, 3, opt.Unwrap()) +} + +func TestOption_IsNone(t *testing.T) { + { + var x = gust.Some[uint32](2) + assert.False(t, x.IsNone()) + } + { + var x = gust.None[uint32]() + assert.True(t, x.IsNone()) + } +} + +func TestOption_IsSomeAnd(t *testing.T) { + { + var x = gust.Some[uint32](2) + assert.True(t, x.IsSomeAnd(func(v uint32) bool { return v > 1 })) + } + { + var x = gust.Some[uint32](0) + assert.False(t, x.IsSomeAnd(func(v uint32) bool { return v > 1 })) + } + { + var x = gust.None[uint32]() + assert.False(t, x.IsSomeAnd(func(v uint32) bool { return v > 1 })) + } +} + +func TestOption_IsSome(t *testing.T) { + { + var x = gust.Some[uint32](2) + assert.True(t, x.IsSome()) + } + { + var x = gust.None[uint32]() + assert.False(t, x.IsSome()) + } +} + +func TestOption_MapOrElse_2(t *testing.T) { + var k = 21 + { + var x = gust.Some("foo") + assert.Equal(t, 3, x.XMapOrElse(func() any { return 2 * k }, func(v string) any { return len(v) })) + } + { + var x gust.Option[string] + assert.Equal(t, 42, x.XMapOrElse(func() any { return 2 * k }, func(v string) any { return len(v) })) + } +} + +func TestOption_MapOr_2(t *testing.T) { + { + var x = gust.Some("foo") + assert.Equal(t, 3, x.XMapOr(42, func(v string) any { return len(v) })) + } + { + var x gust.Option[string] + assert.Equal(t, 42, x.XMapOr(42, func(v string) any { return len(v) })) + } +} + +func TestOption_Map_2(t *testing.T) { + var maybeSomeString = gust.Some("Hello, World!") + var maybeSomeLen = maybeSomeString.XMap(func(s string) any { return len(s) }) + assert.Equal(t, maybeSomeLen, gust.Some(13).ToX()) +} + +func TestOption_OkOrElse(t *testing.T) { + { + var x = gust.Some("foo") + assert.Equal(t, gust.Ok("foo"), x.OkOrElse(func() any { return 0 })) + } + { + var x gust.Option[string] + assert.Equal(t, gust.Err[string](0), x.OkOrElse(func() any { return 0 })) + } +} + +func TestOption_OkOr(t *testing.T) { + { + var x = gust.Some("foo") + assert.Equal(t, gust.Ok("foo"), x.OkOr(0)) + } + { + var x gust.Option[string] + assert.Equal(t, gust.Err[string](0), x.OkOr(0)) + } +} + +func TestOption_OrElse(t *testing.T) { + var nobody = func() gust.Option[string] { return gust.None[string]() } + var vikings = func() gust.Option[string] { return gust.Some("vikings") } + assert.Equal(t, gust.Some("barbarians"), gust.Some("barbarians").OrElse(vikings)) + assert.Equal(t, gust.Some("vikings"), gust.None[string]().OrElse(vikings)) + assert.Equal(t, gust.None[string](), gust.None[string]().OrElse(nobody)) +} + +func TestOption_Or(t *testing.T) { + { + var x = gust.Some[uint32](2) + var y gust.Option[uint32] + assert.Equal(t, gust.Some[uint32](2), x.Or(y)) + } + { + var x gust.Option[uint32] + var y = gust.Some[uint32](100) + assert.Equal(t, gust.Some[uint32](100), x.Or(y)) + } + { + var x = gust.Some[uint32](2) + var y = gust.Some[uint32](100) + assert.Equal(t, gust.Some[uint32](2), x.Or(y)) + } + { + var x gust.Option[uint32] + var y = gust.None[uint32]() + assert.Equal(t, gust.None[uint32](), x.Or(y)) + } +} + +func TestOption_Replace(t *testing.T) { + { + var x = gust.Some(2) + var old = x.Replace(5) + assert.Equal(t, gust.Some(5), x) + assert.Equal(t, gust.Some(2), old) + } + { + var x = gust.None[int]() + var old = x.Replace(3) + assert.Equal(t, gust.Some(3), x) + assert.Equal(t, gust.None[int](), old) + } +} + +func TestOption_Take(t *testing.T) { + { + var x = gust.Some(2) + var y = x.Take() + assert.True(t, x.IsNone()) + assert.Equal(t, gust.Some(2), y) + } + { + var x gust.Option[int] = gust.None[int]() + var y = x.Take() + assert.True(t, x.IsNone()) + assert.True(t, y.IsNone()) + } +} + +func TestOption_UnwrapOrDefault(t *testing.T) { + assert.Equal(t, "car", gust.Some("car").UnwrapOrDefault()) + assert.Equal(t, "", gust.None[string]().UnwrapOrDefault()) + assert.Equal(t, time.Time{}, gust.None[time.Time]().UnwrapOrDefault()) + assert.Equal(t, &time.Time{}, gust.None[*time.Time]().UnwrapOrDefault()) + assert.Equal(t, valconv.Ref(&time.Time{}), gust.None[**time.Time]().UnwrapOrDefault()) +} + +func TestOption_UnwrapOrElse(t *testing.T) { + var k = 10 + assert.Equal(t, 4, gust.Some(4).UnwrapOrElse(func() int { return 2 * k })) + assert.Equal(t, 20, gust.None[int]().UnwrapOrElse(func() int { return 2 * k })) +} + +func TestOption_UnwrapOr(t *testing.T) { + assert.Equal(t, "car", gust.Some("car").UnwrapOr("bike")) + assert.Equal(t, "bike", gust.None[string]().UnwrapOr("bike")) +} + +func TestOption_Unwrap(t *testing.T) { + { + var x = gust.Some("air") + assert.Equal(t, "air", x.Unwrap()) + } + defer func() { + assert.Equal(t, gust.ToErrBox("call Option[string].Unwrap() on none"), recover()) + }() + var x = gust.None[string]() + x.Unwrap() +} + +func TestOption_Xor(t *testing.T) { + { + var x = gust.Some[uint32](2) + var y gust.Option[uint32] + assert.Equal(t, gust.Some[uint32](2), x.Xor(y)) + } + { + var x gust.Option[uint32] + var y = gust.Some[uint32](100) + assert.Equal(t, gust.Some[uint32](100), x.Xor(y)) + } + { + var x = gust.Some[uint32](2) + var y = gust.Some[uint32](100) + assert.Equal(t, gust.None[uint32](), x.Xor(y)) + } + { + var x gust.Option[uint32] + var y = gust.None[uint32]() + assert.Equal(t, gust.None[uint32](), x.Xor(y)) + } +} diff --git a/result_test.go b/result_test.go index fad124a..c2a45b3 100644 --- a/result_test.go +++ b/result_test.go @@ -3,12 +3,62 @@ package gust_test import ( "encoding/json" "errors" + "fmt" + "strconv" + "strings" "testing" + "time" "github.com/andeya/gust" + "github.com/andeya/gust/ret" + "github.com/andeya/gust/valconv" "github.com/stretchr/testify/assert" ) +func ExampleResult_UnwrapOr() { + const def int = 10 + + // before + i, err := strconv.Atoi("1") + if err != nil { + i = def + } + fmt.Println(i * 2) + + // now + fmt.Println(gust.Ret(strconv.Atoi("1")).UnwrapOr(def) * 2) + + // Output: + // 2 + // 2 +} + +// [`Result`] comes with some convenience methods that make working with it more succinct. +func TestResult(t *testing.T) { + var goodResult1 = gust.Ok(10) + var badResult1 = gust.Err[int](10) + + // The `IsOk` and `IsErr` methods do what they say. + assert.True(t, goodResult1.IsOk() && !goodResult1.IsErr()) + assert.True(t, badResult1.IsErr() && !badResult1.IsOk()) + + // `map` consumes the `Result` and produces another. + var goodResult2 = goodResult1.Map(func(i int) int { return i + 1 }) + var badResult2 = badResult1.Map(func(i int) int { return i - 1 }) + + // Use `AndThen` to continue the computation. + var goodResult3 = ret.AndThen(goodResult2, func(i int) gust.Result[bool] { return gust.Ok(i == 11) }) + + // Use `OrElse` to handle the error. + var _ = badResult2.OrElse(func(err error) gust.Result[int] { + fmt.Println(err) + return gust.Ok(20) + }) + + // Consume the result and return the contents with `Unwrap`. + var _ = goodResult3.Unwrap() +} + func TestResultJSON(t *testing.T) { var r = gust.Err[any](errors.New("err")) var b, err = json.Marshal(r) @@ -88,3 +138,282 @@ func TestResultUnwrapOrThrow_3(t *testing.T) { var v2 = r2.UnwrapOrThrow() assert.Equal(t, 0, v2) } + +func TestResult_And(t *testing.T) { + { + x := gust.Ok(2) + y := gust.Err[int]("late error") + assert.Equal(t, gust.Err[int]("late error"), x.And(y)) + } + { + x := gust.Err[uint]("early error") + y := gust.Ok[string]("foo") + assert.Equal(t, gust.Err[any]("early error"), x.XAnd(y.ToX())) + } +} + +func ExampleResult_AndThen() { + var divide = func(i, j float32) gust.Result[float32] { + if j == 0 { + return gust.Err[float32]("j can not be 0") + } + return gust.Ok(i / j) + } + var ret float32 = divide(1, 2).AndThen(func(i float32) gust.Result[float32] { + return gust.Ok(i * 10) + }).Unwrap() + fmt.Println(ret) + // Output: + // 5 +} + +func TestResult_Err(t *testing.T) { + { + var x = gust.Ok[int](2) + assert.Equal(t, error(nil), x.Err()) + } + { + var x = gust.Err[int]("some error message") + assert.Equal(t, "some error message", x.Err().Error()) + } +} + +func TestExpectErr(t *testing.T) { + defer func() { + assert.Equal(t, gust.ToErrBox("Testing expect_err: 10"), recover()) + }() + err := gust.Ok(10).ExpectErr("Testing expect_err") + assert.NoError(t, err) +} + +func TestExpect(t *testing.T) { + defer func() { + assert.Equal(t, "failed to parse number: strconv.Atoi: parsing \"4x\": invalid syntax", recover().(error).Error()) + }() + gust.Ret(strconv.Atoi("4x")). + Expect("failed to parse number") +} + +func TestInspectErr(t *testing.T) { + gust.Ret(strconv.Atoi("4x")). + InspectErr(func(err error) { + t.Logf("failed to convert: %v", err) + }) +} + +func TestInspect(t *testing.T) { + gust.Ret(strconv.Atoi("4")). + Inspect(func(x int) { + fmt.Println("original: ", x) + }). + Map(func(x int) int { + return x * 3 + }). + Expect("failed to parse number") +} + +func TestResult_IsErrAnd(t *testing.T) { + { + var x = gust.Err[int]("hey") + assert.True(t, x.IsErrAnd(func(err error) bool { return err.Error() == "hey" })) + } + { + var x = gust.Ok[int](2) + assert.False(t, x.IsErrAnd(func(err error) bool { return err.Error() == "hey" })) + } +} + +func TestResult_IsErr(t *testing.T) { + { + var x = gust.Ok[int](-3) + assert.False(t, x.IsErr()) + } + { + var x = gust.Err[int]("some error message") + assert.True(t, x.IsErr()) + } +} + +func TestResult_IsOkAnd(t *testing.T) { + { + var x = gust.Ok[int](2) + assert.True(t, x.IsOkAnd(func(x int) bool { return x > 1 })) + } + { + var x = gust.Ok[int](0) + assert.False(t, x.IsOkAnd(func(x int) bool { return x > 1 })) + } + { + var x = gust.Err[int]("hey") + assert.False(t, x.IsOkAnd(func(x int) bool { return x > 1 })) + } +} + +func TestResult_IsOk(t *testing.T) { + { + var x = gust.Ok[int](-3) + assert.True(t, x.IsOk()) + } + { + var x = gust.Err[int]("some error message") + assert.False(t, x.IsOk()) + } +} + +func TestResult_MapErr(t *testing.T) { + var stringify = func(x error) any { return fmt.Sprintf("error code: %v", x) } + { + var x = gust.Ok[uint32](2) + assert.Equal(t, gust.Ok[uint32](2), x.MapErr(stringify)) + } + { + var x = gust.Err[uint32](13) + assert.Equal(t, gust.Err[uint32]("error code: 13"), x.MapErr(stringify)) + } +} + +func TestResult_MapOrElse_2(t *testing.T) { + { + var x = gust.Ok("foo") + assert.Equal(t, "test:foo", x.MapOrElse(func(err error) string { + return "bar" + }, func(x string) string { return "test:" + x })) + } + { + var x = gust.Err[string]("foo") + assert.Equal(t, "bar", x.MapOrElse(func(err error) string { + return "bar" + }, func(x string) string { return "test:" + x })) + } +} + +func TestResult_MapOr_2(t *testing.T) { + { + var x = gust.Ok("foo") + assert.Equal(t, "test:foo", x.MapOr("bar", func(x string) string { return "test:" + x })) + } + { + var x = gust.Err[string]("foo") + assert.Equal(t, "bar", x.MapOr("bar", func(x string) string { return "test:" + x })) + } +} + +func TestResult_Map_1(t *testing.T) { + var line = "1\n2\n3\n4\n" + for _, num := range strings.Split(line, "\n") { + gust.Ret(strconv.Atoi(num)).Map(func(i int) int { + return i * 2 + }).Inspect(func(i int) { + t.Log(i) + }) + } +} + +func TestResult_Map_2(t *testing.T) { + var isMyNum = func(s string, search int) gust.Result[any] { + return gust.Ret(strconv.Atoi(s)).XMap(func(x int) any { return x == search }) + } + assert.Equal(t, gust.Ok[any](true), isMyNum("1", 1)) + assert.Equal(t, gust.Ok[bool](true), ret.XAssert[bool](isMyNum("1", 1))) + assert.Equal(t, "Err(strconv.Atoi: parsing \"lol\": invalid syntax)", isMyNum("lol", 1).String()) + assert.Equal(t, "Err(strconv.Atoi: parsing \"NaN\": invalid syntax)", isMyNum("NaN", 1).String()) +} + +func TestResult_Ok(t *testing.T) { + { + var x = gust.Ok[int](2) + assert.Equal(t, gust.Some[int](2), x.Ok()) + } + { + var x = gust.Err[int]("some error message") + assert.Equal(t, gust.None[int](), x.Ok()) + } +} + +func TestResult_OrElse(t *testing.T) { + var sq = func(x int) gust.EnumResult[int, int] { + return gust.EnumOk[int, int](x * x) + } + var err = func(x int) gust.EnumResult[int, int] { + return gust.EnumErr[int, int](x) + } + + assert.Equal(t, gust.EnumOk[int, int](2).OrElse(sq).OrElse(sq), gust.EnumOk[int, int](2)) + assert.Equal(t, gust.EnumOk[int, int](2).OrElse(err).OrElse(sq), gust.EnumOk[int, int](2)) + assert.Equal(t, gust.EnumErr[int, int](3).OrElse(sq).OrElse(err), gust.EnumOk[int, int](9)) + assert.Equal(t, gust.EnumErr[int, int](3).OrElse(err).OrElse(err), gust.EnumErr[int, int](3)) +} + +func TestResult_Or(t *testing.T) { + { + x := gust.Ok(2) + y := gust.Err[int]("late error") + assert.Equal(t, gust.Ok(2), x.Or(y)) + } + { + x := gust.Err[uint]("early error") + y := gust.Ok[uint](2) + assert.Equal(t, gust.Ok[uint](2), x.Or(y)) + } + { + x := gust.Err[uint]("not a 2") + y := gust.Err[uint]("late error") + assert.Equal(t, gust.Err[uint]("late error"), x.Or(y)) + } + { + x := gust.Ok[uint](2) + y := gust.Ok[uint](100) + assert.Equal(t, gust.Ok[uint](2), x.Or(y)) + } +} + +func TestResult_Ret(t *testing.T) { + var w = gust.Ret[int](strconv.Atoi("s")) + assert.False(t, w.IsOk()) + assert.True(t, w.IsErr()) + + var w2 = gust.Ret[any](strconv.Atoi("-1")) + assert.True(t, w2.IsOk()) + assert.False(t, w2.IsErr()) + assert.Equal(t, -1, w2.Unwrap()) +} + +func TestUnwrapErr_1(t *testing.T) { + defer func() { + assert.Equal(t, gust.ToErrBox("called `Result.UnwrapErr()` on an `ok` value: 10"), recover()) + }() + err := gust.Ok(10).UnwrapErr() + assert.NoError(t, err) +} + +func TestUnwrapErr_2(t *testing.T) { + err := gust.Err[int]("emergency failure").UnwrapErr() + if assert.Error(t, err) { + assert.Equal(t, "emergency failure", err.Error()) + } else { + t.FailNow() + } +} + +func TestUnwrapOrDefault(t *testing.T) { + assert.Equal(t, "car", gust.Ok("car").UnwrapOrDefault()) + assert.Equal(t, "", gust.Err[string](nil).UnwrapOrDefault()) + assert.Equal(t, time.Time{}, gust.Err[time.Time](nil).UnwrapOrDefault()) + assert.Equal(t, &time.Time{}, gust.Err[*time.Time](nil).UnwrapOrDefault()) + assert.Equal(t, valconv.Ref(&time.Time{}), gust.Err[**time.Time](nil).UnwrapOrDefault()) +} + +func TestUnwrapOrElse(t *testing.T) { + var count = func(x error) int { + return len(x.Error()) + } + assert.Equal(t, 2, gust.Ok(2).UnwrapOrElse(count)) + assert.Equal(t, 3, gust.Err[int]("foo").UnwrapOrElse(count)) +} + +func TestUnwrap(t *testing.T) { + defer func() { + assert.Equal(t, "strconv.Atoi: parsing \"4x\": invalid syntax", recover().(error).Error()) + }() + gust.Ret(strconv.Atoi("4x")).Unwrap() +} diff --git a/ret/result_test.go b/ret/result_test.go new file mode 100644 index 0000000..ceef3b7 --- /dev/null +++ b/ret/result_test.go @@ -0,0 +1,70 @@ +package ret_test + +import ( + "fmt" + "strconv" + "testing" + + "github.com/andeya/gust" + "github.com/andeya/gust/ret" + "github.com/stretchr/testify/assert" +) + +func TestAssert(t *testing.T) { + r := gust.Ok[any]("hello") + assert.Equal(t, "gust.Result[string]", fmt.Sprintf("%T", ret.Assert[any, string](r))) +} + +func TestXAssert(t *testing.T) { + r := gust.Ok[any]("hello") + assert.Equal(t, "gust.Result[string]", fmt.Sprintf("%T", ret.XAssert[string](r))) +} + +func TestResult_ContainsErr(t *testing.T) { + assert.False(t, gust.Ok(2).ContainsErr("Some error message")) + assert.True(t, ret.Contains(gust.Ok(2), 2)) + assert.False(t, ret.Contains(gust.Ok(3), 2)) + assert.False(t, ret.Contains(gust.Err[int]("Some error message"), 2)) +} + +func TestResult_Contains(t *testing.T) { + assert.True(t, ret.Contains(gust.Ok(2), 2)) + assert.False(t, ret.Contains(gust.Ok(3), 2)) + assert.False(t, ret.Contains(gust.Err[int]("Some error message"), 2)) +} + +func TestResult_MapOrElse_1(t *testing.T) { + var k = 21 + { + var x = gust.Ok("foo") + assert.Equal(t, 3, ret.MapOrElse(x, func(err error) int { + return k * 2 + }, func(x string) int { return len(x) })) + } + { + var x = gust.Err[string]("bar") + assert.Equal(t, 42, ret.MapOrElse(x, func(err error) int { + return k * 2 + }, func(x string) int { return len(x) })) + } +} + +func TestResult_MapOr_1(t *testing.T) { + { + var x = gust.Ok("foo") + assert.Equal(t, 3, ret.MapOr(x, 42, func(x string) int { return len(x) })) + } + { + var x = gust.Err[string]("foo") + assert.Equal(t, 42, ret.MapOr(x, 42, func(x string) int { return len(x) })) + } +} + +func TestResult_Map_3(t *testing.T) { + var isMyNum = func(s string, search int) gust.Result[bool] { + return ret.Map(gust.Ret(strconv.Atoi(s)), func(x int) bool { return x == search }) + } + assert.Equal(t, gust.Ok[bool](true), isMyNum("1", 1)) + assert.Equal(t, "Err(strconv.Atoi: parsing \"lol\": invalid syntax)", isMyNum("lol", 1).String()) + assert.Equal(t, "Err(strconv.Atoi: parsing \"NaN\": invalid syntax)", isMyNum("NaN", 1).String()) +}