Compare commits
10 Commits
4f5871af53
...
df716e8fe0
Author | SHA1 | Date |
---|---|---|
Charles Iliya Krempeaux | df716e8fe0 | |
Charles Iliya Krempeaux | 89498dfdf6 | |
Charles Iliya Krempeaux | bb61bb0854 | |
Charles Iliya Krempeaux | 4cd974c11f | |
Charles Iliya Krempeaux | bfb598fbd1 | |
Charles Iliya Krempeaux | d7e8552eea | |
Charles Iliya Krempeaux | 9cbd049b34 | |
Charles Iliya Krempeaux | e86446ff5b | |
Charles Iliya Krempeaux | 96351d3ad7 | |
Charles Iliya Krempeaux | 258a41bedc |
2
LICENSE
2
LICENSE
|
@ -1,4 +1,4 @@
|
||||||
Copyright (c) 2017 Charles Iliya Krempeaux <charles@reptile.ca> :: http://changelog.ca/
|
Copyright (c) 2017 Charles Iliya Krempeaux :: http://changelog.ca/
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
56
README.md
56
README.md
|
@ -1,14 +1,56 @@
|
||||||
# go-opt
|
# go-opt
|
||||||
|
|
||||||
Package **opt** provides alternatives to Go's built-in types (bool, float64, int64, string, time.Time)
|
Package **opt** implements an **optional-type**, for the Go programming language.
|
||||||
that also let you express a "lack of a value"; for the Go programming language;
|
|
||||||
these are similar to "option types" or "maybe types" in some other programming languages.
|
|
||||||
|
|
||||||
(Code for this was generated using https://github.com/reiver/gogen-optiontype )
|
|
||||||
|
|
||||||
|
In other programming languages, an **optional-type** might be know as: a **option-type**, or a **maybe-type**.
|
||||||
|
|
||||||
## Documention
|
## Documention
|
||||||
|
|
||||||
Online documentation, which includes examples, can be found at: http://godoc.org/github.com/reiver/go-opt
|
Online documentation, which includes examples, can be found at: http://godoc.org/sourcecode.social/reiver/go-opt
|
||||||
|
|
||||||
[![GoDoc](https://godoc.org/github.com/reiver/go-opt?status.svg)](https://godoc.org/github.com/reiver/go-opt)
|
[![GoDoc](https://godoc.org/sourcecode.social/reiver/go-opt?status.svg)](https://godoc.org/sourcecode.social/reiver/go-opt)
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
Here is an example **optional-type** that can hold a string:
|
||||||
|
```go
|
||||||
|
import "sourcecode.social/reiver/go-opt"
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
var op opt.Optional[string] // the default value is nothing.
|
||||||
|
|
||||||
|
// ...
|
||||||
|
|
||||||
|
if opt.Nothing[string]() == op {
|
||||||
|
fmt.Println("nothing")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ...
|
||||||
|
|
||||||
|
op = opt.Something("Hello world! 👾")
|
||||||
|
|
||||||
|
// ...
|
||||||
|
|
||||||
|
switch op {
|
||||||
|
case op.Nothing[string]():
|
||||||
|
//@TODO
|
||||||
|
case op.Something("apple"):
|
||||||
|
//@TODO
|
||||||
|
case op.Something("banana"):
|
||||||
|
//@TODO
|
||||||
|
case op.Something("cherry"):
|
||||||
|
//@TODO
|
||||||
|
default:
|
||||||
|
//@TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
// ...
|
||||||
|
|
||||||
|
value, found := op.Get()
|
||||||
|
if found {
|
||||||
|
fmt.Println("VALUE:", value)
|
||||||
|
} else {
|
||||||
|
fmt.Println("nothing")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
43
doc.go
43
doc.go
|
@ -1,43 +0,0 @@
|
||||||
/*
|
|
||||||
Package opt has a number of sub-packages provides alternatives to Go's built-in types (bool, float64, int64, string, time.Time)
|
|
||||||
that also let you express a "lack of a value"; for the Go programming language; these are similar to "option types" or "maybe types"
|
|
||||||
in some other programming languages.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
var s optstring.NullableType
|
|
||||||
|
|
||||||
// ...
|
|
||||||
|
|
||||||
switch s {
|
|
||||||
case optstring.NoneNullable():
|
|
||||||
//@TODO
|
|
||||||
case optstring.Null():
|
|
||||||
//@TODO
|
|
||||||
case optstring.SomeNullable("Hello world!"):
|
|
||||||
//@TODO
|
|
||||||
case optstring.SomeNullable("apple banana cherry"):
|
|
||||||
//@TODO
|
|
||||||
default:
|
|
||||||
//@TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
var s optstring.Type
|
|
||||||
|
|
||||||
// ...
|
|
||||||
|
|
||||||
switch s {
|
|
||||||
case optstring.None():
|
|
||||||
//@TODO
|
|
||||||
case optstring.Some("Hello world!"):
|
|
||||||
//@TODO
|
|
||||||
case optstring.Some("apple banana cherry"):
|
|
||||||
//@TODO
|
|
||||||
default:
|
|
||||||
//@TODO
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
package opt
|
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
package opt
|
||||||
|
|
||||||
|
// Map applies the function ‘fn’ to the value inside of the optional-type ‘op’, if the optional-type ‘op’ is holding something, and returns it as a new optional-type.
|
||||||
|
// If the optional-type ‘op’ is holding nothing, then Map also returns nothing.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
//
|
||||||
|
// var op opt.Optional[string] = opt.Something("Hello world!")
|
||||||
|
//
|
||||||
|
// var result opt.Optional[string] = opt.Map(op, strings.ToUpper)
|
||||||
|
//
|
||||||
|
// // result == opt.Something[string]("HELLO WORLD!")
|
||||||
|
//
|
||||||
|
// // ...
|
||||||
|
//
|
||||||
|
// var op2 opt.Optional[string] = opt.Nothing[string]()
|
||||||
|
//
|
||||||
|
// var result2 opt.Optional[string] = opt.Map(op, strings.ToUpper)
|
||||||
|
//
|
||||||
|
// // result2 == opt.Nothing[string]()
|
||||||
|
//
|
||||||
|
// Or also, for example:
|
||||||
|
//
|
||||||
|
// fn := func(s string) int {
|
||||||
|
// return len(s)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// var op opt.Optional[string] = opt.Something("Hello world!")
|
||||||
|
//
|
||||||
|
// var result opt.Optional[int] = opt.Map(op, fn)
|
||||||
|
//
|
||||||
|
// // result == opt.Something[int](12)
|
||||||
|
//
|
||||||
|
// // ...
|
||||||
|
//
|
||||||
|
// var op2 opt.Optional[string] = opt.Nothing[string]()
|
||||||
|
//
|
||||||
|
// var result2 opt.Optional[int] = opt.Map(op, fn)
|
||||||
|
//
|
||||||
|
// // result2 == opt.Nothing[int]()
|
||||||
|
func Map[T1 any, T2 any](op Optional[T1], fn func(T1)T2) Optional[T2] {
|
||||||
|
if !op.something {
|
||||||
|
return Nothing[T2]()
|
||||||
|
}
|
||||||
|
|
||||||
|
return Something(fn(op.value))
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
package opt_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sourcecode.social/reiver/go-opt"
|
||||||
|
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMap_stringToUint(t *testing.T) {
|
||||||
|
|
||||||
|
tests := []struct{
|
||||||
|
Optional opt.Optional[string]
|
||||||
|
Expected opt.Optional[int]
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Optional: opt.Nothing[string](),
|
||||||
|
Expected: opt.Nothing[int](),
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
Optional: opt.Something(""),
|
||||||
|
Expected: opt.Something[int](0),
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
Optional: opt.Something("once"),
|
||||||
|
Expected: opt.Something[int](4),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something("twice"),
|
||||||
|
Expected: opt.Something[int](5),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something("thrice"),
|
||||||
|
Expected: opt.Something[int](6),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something("fource"),
|
||||||
|
Expected: opt.Something[int](6),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for testNumber, test := range tests {
|
||||||
|
|
||||||
|
fn := func(s string) int {
|
||||||
|
return len(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
mapped := opt.Map(test.Optional, fn)
|
||||||
|
|
||||||
|
{
|
||||||
|
expected := test.Expected
|
||||||
|
actual := mapped
|
||||||
|
|
||||||
|
if expected != actual {
|
||||||
|
t.Errorf("For test #%d, the actual value is not what was expected.", testNumber)
|
||||||
|
t.Logf("EXPECTED: (%T) %#v", expected, expected)
|
||||||
|
t.Logf("ACTUAL: (%T) %#v", actual, actual)
|
||||||
|
t.Logf("OPTIONAL: (%T), %#v", test.Optional, test.Optional)
|
||||||
|
/////////////////////// CONTINUE
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,209 @@
|
||||||
|
package opt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Optional represents an optional value.
|
||||||
|
//
|
||||||
|
// In other programming languages this is know as: an option type, or a maybe type.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
//
|
||||||
|
// var op opt.Optional[string] = opt.Something("once twice thrice fource")
|
||||||
|
//
|
||||||
|
// // ...
|
||||||
|
//
|
||||||
|
// value, found := op.Get()
|
||||||
|
// if found {
|
||||||
|
// fmt.Println("value:", value)
|
||||||
|
// } else{
|
||||||
|
// fmt.Println("nothing")
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Also, for example:
|
||||||
|
//
|
||||||
|
// var op opt.Optional[uint8] = opt.Something[uint8](101)
|
||||||
|
//
|
||||||
|
// // ...
|
||||||
|
//
|
||||||
|
// value, found := op.Get()
|
||||||
|
// if found {
|
||||||
|
// fmt.Println("value:", value)
|
||||||
|
// } else{
|
||||||
|
// fmt.Println("nothing")
|
||||||
|
// }
|
||||||
|
type Optional[T any] struct {
|
||||||
|
value T
|
||||||
|
something bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nothing returns an optional-type with nothing in it.
|
||||||
|
//
|
||||||
|
// For example, here is an optional-type that can hold a string with nothing in it:
|
||||||
|
//
|
||||||
|
// var op opt.Optional[string] = opt.Nothing[string]()
|
||||||
|
//
|
||||||
|
// Note that the default value for any optional-type is nothing.
|
||||||
|
// So the following code it equivalent to it:
|
||||||
|
//
|
||||||
|
// var op opt.Optional[string]
|
||||||
|
//
|
||||||
|
// Also, for example, here is an optional-type that can hold a uint8 with nothing in it:
|
||||||
|
//
|
||||||
|
// var op opt.Optional[uint8] = opt.Nothing[uint8]()
|
||||||
|
//
|
||||||
|
// Again, note that the default value for any optional-type is nothing.
|
||||||
|
// So the following code it equivalent to it:
|
||||||
|
//
|
||||||
|
// var op opt.Optional[uint8]
|
||||||
|
func Nothing[T any]() Optional[T] {
|
||||||
|
var nothing Optional[T]
|
||||||
|
|
||||||
|
return nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
// Something returns a optional-type with something in it.
|
||||||
|
//
|
||||||
|
// For example, here is an optional-type with the string "once twice thrice fource" in it:
|
||||||
|
//
|
||||||
|
// var op opt.Optional[string] = opt.Something("once twice thrice fource")
|
||||||
|
//
|
||||||
|
// And, for example, here is an optional-type with the uint8 101 in it:
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// var op opt.Optional[uint8] = opt.Something(uint8(101))
|
||||||
|
func Something[T any](value T) Optional[T] {
|
||||||
|
return Optional[T]{
|
||||||
|
something:true,
|
||||||
|
value:value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter returns itself if it is holding something and ‘fn’ applied to its value returns true.
|
||||||
|
// Else it return nothing.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
//
|
||||||
|
// fn := func(value int) bool {
|
||||||
|
// return 0 == (value % 2)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // ...
|
||||||
|
//
|
||||||
|
// var op1 opt.Optional[int] = opt.Something[int](10)
|
||||||
|
//
|
||||||
|
// op1 = op1.Filter(fn)
|
||||||
|
//
|
||||||
|
// // ...
|
||||||
|
//
|
||||||
|
// var op2 opt.Optional[int] = opt.Something[int](11)
|
||||||
|
//
|
||||||
|
// op2 = op2.Filter(fn)
|
||||||
|
//
|
||||||
|
// // ...
|
||||||
|
//
|
||||||
|
// var op3 opt.Optional[int] = opt.Nothing[int]()
|
||||||
|
//
|
||||||
|
// op3 = op3.Filter(fn)
|
||||||
|
func (receiver Optional[T]) Filter(fn func(T)bool) Optional[T] {
|
||||||
|
if !receiver.something {
|
||||||
|
return Nothing[T]()
|
||||||
|
}
|
||||||
|
|
||||||
|
if !fn(receiver.value) {
|
||||||
|
return Nothing[T]()
|
||||||
|
}
|
||||||
|
|
||||||
|
return receiver
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns the value inside of the optional-type if it is holding something.
|
||||||
|
//
|
||||||
|
// Example usage:
|
||||||
|
//
|
||||||
|
// var op opt.Optional[string]
|
||||||
|
//
|
||||||
|
// // ...
|
||||||
|
//
|
||||||
|
// value, found := op.Get()
|
||||||
|
//
|
||||||
|
// if found {
|
||||||
|
// fmt.Println("VALUE:", value)
|
||||||
|
// } else {
|
||||||
|
// fmt.Println("nothing")
|
||||||
|
// }
|
||||||
|
func (receiver Optional[T]) Get() (T, bool) {
|
||||||
|
return receiver.value, receiver.something
|
||||||
|
}
|
||||||
|
|
||||||
|
// GoString makes it that when the fmt.Fprintf(), fmt.Printf(), and fmt.Sprintf() family of functions
|
||||||
|
// renders this type with the %#v verb, that it will be easier to understand.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
//
|
||||||
|
// var op opt.Optional[string] = opt.Something("once twice thrice fource")
|
||||||
|
//
|
||||||
|
// // ...
|
||||||
|
//
|
||||||
|
// fmt.Printf("op = %#v", op)
|
||||||
|
//
|
||||||
|
// // Output:
|
||||||
|
// // op = opt.Something[string]("once twice thrice fource")
|
||||||
|
//
|
||||||
|
// Also, for example:
|
||||||
|
//
|
||||||
|
// var op opt.Optional[uint8] = opt.Nothing[uint8]()
|
||||||
|
//
|
||||||
|
// // ...
|
||||||
|
//
|
||||||
|
// fmt.Printf("op = %#v", op)
|
||||||
|
//
|
||||||
|
// // Output:
|
||||||
|
// // op = opt.Nothing[uint8]()
|
||||||
|
func (receiver Optional[T]) GoString() string {
|
||||||
|
if !receiver.something {
|
||||||
|
return fmt.Sprintf("opt.Nothing[%T]()", receiver.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("opt.Something[%T](%#v)", receiver.value, receiver.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhenNothing will call ‘fn’ when ‘receiver’ is holding nothing.
|
||||||
|
//
|
||||||
|
// It will not call ‘fn’ when ‘receier’ is hold something.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
//
|
||||||
|
// var op opt.Optional = opt.Nothing[string]
|
||||||
|
//
|
||||||
|
// // ...
|
||||||
|
//
|
||||||
|
// op.WhenNothing(func(){
|
||||||
|
// //@TODO
|
||||||
|
// })
|
||||||
|
func (receiver Optional[T]) WhenNothing(fn func()) {
|
||||||
|
if !receiver.something {
|
||||||
|
fn()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhenSomething will ‘fn’ when ‘receiver’ is holding something.
|
||||||
|
// The value that ‘receiver’ is holding will be passed as a parameter to the function ‘fn’.
|
||||||
|
//
|
||||||
|
// It will not call ‘fn’ when ‘receiver’ is hold nothing.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
//
|
||||||
|
// var op opt.Optional = opt.Something("once twice thrice fource")
|
||||||
|
//
|
||||||
|
// // ...
|
||||||
|
//
|
||||||
|
// op.WhenSomething(func(value string){
|
||||||
|
// //@TODO
|
||||||
|
// })
|
||||||
|
func (receiver Optional[T]) WhenSomething(fn func(T)) {
|
||||||
|
if receiver.something {
|
||||||
|
fn(receiver.value)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
package opt_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sourcecode.social/reiver/go-opt"
|
||||||
|
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestOptional_Filter_int(t *testing.T) {
|
||||||
|
|
||||||
|
tests := []struct{
|
||||||
|
Optional opt.Optional[int]
|
||||||
|
Expected opt.Optional[int]
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Optional: opt.Nothing[int](),
|
||||||
|
Expected: opt.Nothing[int](),
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int](-2),
|
||||||
|
Expected: opt.Something[int](-2),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int](-1),
|
||||||
|
Expected: opt.Nothing[int](),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int](0),
|
||||||
|
Expected: opt.Something[int](0),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int](1),
|
||||||
|
Expected: opt.Nothing[int](),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int](2),
|
||||||
|
Expected: opt.Something[int](2),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for testNumber, test := range tests {
|
||||||
|
|
||||||
|
fn := func(value int) bool {
|
||||||
|
return 0 == (value % 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
actual := test.Optional.Filter(fn)
|
||||||
|
expected := test.Expected
|
||||||
|
|
||||||
|
if expected != actual {
|
||||||
|
t.Errorf("For test #%d, the actual value is not what was expected.", testNumber)
|
||||||
|
t.Logf("EXPECTED: %#v", expected)
|
||||||
|
t.Logf("ACTUAL: %#v", actual)
|
||||||
|
/////////////// CONTINUE
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,380 @@
|
||||||
|
package opt_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sourcecode.social/reiver/go-opt"
|
||||||
|
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestOptional_Get_string(t *testing.T) {
|
||||||
|
|
||||||
|
tests := []struct{
|
||||||
|
Optional opt.Optional[string]
|
||||||
|
ExpectedValue string
|
||||||
|
ExpectedSomething bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Optional: opt.Nothing[string](),
|
||||||
|
ExpectedValue: "",
|
||||||
|
ExpectedSomething: false,
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
Optional: opt.Something(""),
|
||||||
|
ExpectedValue: "",
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something("once twice thrice fource"),
|
||||||
|
ExpectedValue: "once twice thrice fource",
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something("😈"),
|
||||||
|
ExpectedValue: "😈",
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something("۰۱۲۳۴۵۶۷۸۹"),
|
||||||
|
ExpectedValue: "۰۱۲۳۴۵۶۷۸۹",
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for testNumber, test := range tests {
|
||||||
|
|
||||||
|
value, something := test.Optional.Get()
|
||||||
|
|
||||||
|
{
|
||||||
|
expected := test.ExpectedSomething
|
||||||
|
actual := something
|
||||||
|
|
||||||
|
if expected != actual {
|
||||||
|
t.Errorf("For test #%d, the actual something-flag is not what was expected.", testNumber)
|
||||||
|
t.Logf("EXPECTED FLAG: %t", expected)
|
||||||
|
t.Logf("ACTUAL FLAG: %t", actual)
|
||||||
|
t.Logf("OPTIONAL: %#v", test.Optional)
|
||||||
|
/////////////////////// CONTINUE
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
expected := test.ExpectedValue
|
||||||
|
actual := value
|
||||||
|
|
||||||
|
if expected != actual {
|
||||||
|
t.Errorf("For test #%d, the actual value is not what was expected.", testNumber)
|
||||||
|
t.Logf("EXPECTED VALUE: %q", expected)
|
||||||
|
t.Logf("ACTUAL VALUE: %q", actual)
|
||||||
|
t.Logf("OPTIONAL: %#v", test.Optional)
|
||||||
|
/////////////////////// CONTINUE
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOptional_Get_int8(t *testing.T) {
|
||||||
|
|
||||||
|
tests := []struct{
|
||||||
|
Optional opt.Optional[int8]
|
||||||
|
ExpectedValue int8
|
||||||
|
ExpectedSomething bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Optional: opt.Nothing[int8](),
|
||||||
|
ExpectedValue: 0,
|
||||||
|
ExpectedSomething: false,
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
Optional: opt.Something(int8(-127)),
|
||||||
|
ExpectedValue: int8(-127),
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something(int8(-126)),
|
||||||
|
ExpectedValue: int8(-126),
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something(int8(-125)),
|
||||||
|
ExpectedValue: int8(-125),
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something(int8(-124)),
|
||||||
|
ExpectedValue: int8(-124),
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something(int8(-123)),
|
||||||
|
ExpectedValue: int8(-123),
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something(int8(-122)),
|
||||||
|
ExpectedValue: int8(-122),
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something(int8(-121)),
|
||||||
|
ExpectedValue: int8(-121),
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something(int8(-120)),
|
||||||
|
ExpectedValue: int8(-120),
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something(int8(-9)),
|
||||||
|
ExpectedValue: int8(-9),
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something(int8(-8)),
|
||||||
|
ExpectedValue: int8(-8),
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something(int8(-7)),
|
||||||
|
ExpectedValue: int8(-7),
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something(int8(-6)),
|
||||||
|
ExpectedValue: int8(-6),
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something(int8(-5)),
|
||||||
|
ExpectedValue: int8(-5),
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something(int8(-4)),
|
||||||
|
ExpectedValue: int8(-4),
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something(int8(-3)),
|
||||||
|
ExpectedValue: int8(-3),
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something(int8(-2)),
|
||||||
|
ExpectedValue: int8(-2),
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something(int8(-1)),
|
||||||
|
ExpectedValue: int8(-1),
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something(int8(0)),
|
||||||
|
ExpectedValue: int8(0),
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something(int8(1)),
|
||||||
|
ExpectedValue: int8(1),
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something(int8(2)),
|
||||||
|
ExpectedValue: int8(2),
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something(int8(3)),
|
||||||
|
ExpectedValue: int8(3),
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something(int8(4)),
|
||||||
|
ExpectedValue: int8(4),
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something(int8(5)),
|
||||||
|
ExpectedValue: int8(5),
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something(int8(6)),
|
||||||
|
ExpectedValue: int8(6),
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something(int8(7)),
|
||||||
|
ExpectedValue: int8(7),
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something(int8(8)),
|
||||||
|
ExpectedValue: int8(8),
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something(int8(9)),
|
||||||
|
ExpectedValue: int8(9),
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something(int8(120)),
|
||||||
|
ExpectedValue: int8(120),
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something(int8(121)),
|
||||||
|
ExpectedValue: int8(121),
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something(int8(122)),
|
||||||
|
ExpectedValue: int8(122),
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something(int8(123)),
|
||||||
|
ExpectedValue: int8(123),
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something(int8(124)),
|
||||||
|
ExpectedValue: int8(124),
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something(int8(125)),
|
||||||
|
ExpectedValue: int8(125),
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something(int8(126)),
|
||||||
|
ExpectedValue: int8(126),
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something(int8(127)),
|
||||||
|
ExpectedValue: int8(127),
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for testNumber, test := range tests {
|
||||||
|
|
||||||
|
value, something := test.Optional.Get()
|
||||||
|
|
||||||
|
{
|
||||||
|
expected := test.ExpectedSomething
|
||||||
|
actual := something
|
||||||
|
|
||||||
|
if expected != actual {
|
||||||
|
t.Errorf("For test #%d, the actual something-flag is not what was expected.", testNumber)
|
||||||
|
t.Logf("EXPECTED FLAG: %t", expected)
|
||||||
|
t.Logf("ACTUAL FLAG: %t", actual)
|
||||||
|
t.Logf("OPTIONAL: %#v", test.Optional)
|
||||||
|
/////////////////////// CONTINUE
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
expected := test.ExpectedValue
|
||||||
|
actual := value
|
||||||
|
|
||||||
|
if expected != actual {
|
||||||
|
t.Errorf("For test #%d, the actual value is not what was expected.", testNumber)
|
||||||
|
t.Logf("EXPECTED VALUE: %q", expected)
|
||||||
|
t.Logf("ACTUAL VALUE: %q", actual)
|
||||||
|
t.Logf("OPTIONAL: %#v", test.Optional)
|
||||||
|
/////////////////////// CONTINUE
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOptional_Get_uint8(t *testing.T) {
|
||||||
|
|
||||||
|
tests := []struct{
|
||||||
|
Optional opt.Optional[uint8]
|
||||||
|
ExpectedValue uint8
|
||||||
|
ExpectedSomething bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Optional: opt.Nothing[uint8](),
|
||||||
|
ExpectedValue: 0,
|
||||||
|
ExpectedSomething: false,
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
Optional: opt.Something(uint8(0)),
|
||||||
|
ExpectedValue: uint8(0),
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something(uint8(1)),
|
||||||
|
ExpectedValue: uint8(1),
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something(uint8(2)),
|
||||||
|
ExpectedValue: uint8(2),
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something(uint8(254)),
|
||||||
|
ExpectedValue: uint8(254),
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something(uint8(255)),
|
||||||
|
ExpectedValue: uint8(255),
|
||||||
|
ExpectedSomething: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for testNumber, test := range tests {
|
||||||
|
|
||||||
|
value, something := test.Optional.Get()
|
||||||
|
|
||||||
|
{
|
||||||
|
expected := test.ExpectedSomething
|
||||||
|
actual := something
|
||||||
|
|
||||||
|
if expected != actual {
|
||||||
|
t.Errorf("For test #%d, the actual something-flag is not what was expected.", testNumber)
|
||||||
|
t.Logf("EXPECTED FLAG: %t", expected)
|
||||||
|
t.Logf("ACTUAL FLAG: %t", actual)
|
||||||
|
t.Logf("OPTIONAL: %#v", test.Optional)
|
||||||
|
/////////////////////// CONTINUE
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
expected := test.ExpectedValue
|
||||||
|
actual := value
|
||||||
|
|
||||||
|
if expected != actual {
|
||||||
|
t.Errorf("For test #%d, the actual value is not what was expected.", testNumber)
|
||||||
|
t.Logf("EXPECTED VALUE: %q", expected)
|
||||||
|
t.Logf("ACTUAL VALUE: %q", actual)
|
||||||
|
t.Logf("OPTIONAL: %#v", test.Optional)
|
||||||
|
/////////////////////// CONTINUE
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,191 @@
|
||||||
|
package opt_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sourcecode.social/reiver/go-opt"
|
||||||
|
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestOptional_GoString(t *testing.T) {
|
||||||
|
|
||||||
|
tests := []struct{
|
||||||
|
Value any
|
||||||
|
Expected string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Value: "",
|
||||||
|
Expected: `opt.Something[string]("")`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "once twice thrice fource",
|
||||||
|
Expected: `opt.Something[string]("once twice thrice fource")`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "apple banana cherry",
|
||||||
|
Expected: `opt.Something[string]("apple banana cherry")`,
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
Value: uint8 (0x0),
|
||||||
|
Expected: `opt.Something[uint8](0x0)`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: uint8 (0x1),
|
||||||
|
Expected: `opt.Something[uint8](0x1)`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: uint8 (0x2),
|
||||||
|
Expected: `opt.Something[uint8](0x2)`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: uint8 (0xfe),
|
||||||
|
Expected: `opt.Something[uint8](0xfe)`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: uint8 (0xff),
|
||||||
|
Expected: `opt.Something[uint8](0xff)`,
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
Value: uint16 (0x0),
|
||||||
|
Expected: `opt.Something[uint16](0x0)`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: uint16 (0x1),
|
||||||
|
Expected: `opt.Something[uint16](0x1)`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: uint16 (0x2),
|
||||||
|
Expected: `opt.Something[uint16](0x2)`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: uint16 (0xfe),
|
||||||
|
Expected: `opt.Something[uint16](0xfe)`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: uint16 (0xff),
|
||||||
|
Expected: `opt.Something[uint16](0xff)`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: uint16 (0x100),
|
||||||
|
Expected: `opt.Something[uint16](0x100)`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: uint16 (0x101),
|
||||||
|
Expected: `opt.Something[uint16](0x101)`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: uint16 (0x102),
|
||||||
|
Expected: `opt.Something[uint16](0x102)`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: uint16 (0xfffe),
|
||||||
|
Expected: `opt.Something[uint16](0xfffe)`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: uint16 (0xffff),
|
||||||
|
Expected: `opt.Something[uint16](0xffff)`,
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
Value: struct { A string; B int }{A:"joeblow",B:7},
|
||||||
|
Expected: `opt.Something[struct { A string; B int }](struct { A string; B int }{A:"joeblow", B:7})`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for testNumber, test := range tests {
|
||||||
|
|
||||||
|
op := opt.Something(test.Value)
|
||||||
|
gostring := op.GoString()
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
expected := test.Expected
|
||||||
|
actual := gostring
|
||||||
|
|
||||||
|
if expected != actual {
|
||||||
|
t.Errorf("For test #%d, the actual go-string is not what was expected.", testNumber)
|
||||||
|
t.Logf("EXPECTED: %q", expected)
|
||||||
|
t.Logf("ACTUAL: %q", actual)
|
||||||
|
t.Logf("VALUE-TYPE: %T", test.Value)
|
||||||
|
t.Logf("VALUE: %#v", test.Value)
|
||||||
|
//////////////////////// CONTINUE
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOptional_GoString_nothing(t *testing.T) {
|
||||||
|
|
||||||
|
tests := []struct{
|
||||||
|
Optional fmt.GoStringer
|
||||||
|
Expected string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Optional: opt.Nothing[string](),
|
||||||
|
Expected: `opt.Nothing[string]()`,
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
Optional: opt.Nothing[int8](),
|
||||||
|
Expected: `opt.Nothing[int8]()`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Nothing[int16](),
|
||||||
|
Expected: `opt.Nothing[int16]()`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Nothing[int32](),
|
||||||
|
Expected: `opt.Nothing[int32]()`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Nothing[int64](),
|
||||||
|
Expected: `opt.Nothing[int64]()`,
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
Optional: opt.Nothing[uint8](),
|
||||||
|
Expected: `opt.Nothing[uint8]()`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Nothing[uint16](),
|
||||||
|
Expected: `opt.Nothing[uint16]()`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Nothing[uint32](),
|
||||||
|
Expected: `opt.Nothing[uint32]()`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Nothing[uint64](),
|
||||||
|
Expected: `opt.Nothing[uint64]()`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for testNumber, test := range tests {
|
||||||
|
|
||||||
|
expected := test.Expected
|
||||||
|
actual := test.Optional.GoString()
|
||||||
|
|
||||||
|
if expected != actual {
|
||||||
|
t.Errorf("For test #%d, the actual go-string value is not what was expected.", testNumber)
|
||||||
|
t.Logf("EXPECTED GO-STRING: %q", expected)
|
||||||
|
t.Logf("ACTUAL GO-STRING: %q", actual)
|
||||||
|
t.Logf("TYPE: %T", test.Optional)
|
||||||
|
/////////////// CONTINUE
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,139 @@
|
||||||
|
package opt_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sourcecode.social/reiver/go-opt"
|
||||||
|
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestOptional_WhenNothing(t *testing.T) {
|
||||||
|
|
||||||
|
|
||||||
|
tests := []struct{
|
||||||
|
Optional interface{WhenNothing(func())}
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Optional: opt.Nothing[string](),
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
Optional: opt.Nothing[int](),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Nothing[int8](),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Nothing[int16](),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Nothing[int32](),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Nothing[int64](),
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
Optional: opt.Nothing[uint](),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Nothing[uint8](),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Nothing[uint16](),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Nothing[uint32](),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Nothing[uint64](),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for testNumber, test := range tests {
|
||||||
|
|
||||||
|
var worked bool = false
|
||||||
|
|
||||||
|
test.Optional.WhenNothing(func(){
|
||||||
|
|
||||||
|
worked = true
|
||||||
|
})
|
||||||
|
|
||||||
|
if !worked {
|
||||||
|
t.Errorf("For test #%d, the call to the method did not seem work.", testNumber)
|
||||||
|
t.Logf("WORKED: %t", worked)
|
||||||
|
t.Logf("OPTIONAL: (%T) %#v", test.Optional, test.Optional)
|
||||||
|
//////////////// CONTINUE
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOptional_WhenNothing_something(t *testing.T) {
|
||||||
|
|
||||||
|
|
||||||
|
tests := []struct{
|
||||||
|
Optional interface{WhenNothing(func())}
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Optional: opt.Something[string]("once twice thrice fource"),
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int](-1),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int8](-101),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int16](-10101),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int32](-1010101),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int64](-101010101),
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
Optional: opt.Something[uint](1),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[uint8](101),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[uint16](10101),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[uint32](1010101),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[uint64](101010101),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for testNumber, test := range tests {
|
||||||
|
|
||||||
|
var worked bool = false
|
||||||
|
|
||||||
|
test.Optional.WhenNothing(func(){
|
||||||
|
|
||||||
|
worked = true
|
||||||
|
})
|
||||||
|
|
||||||
|
if worked {
|
||||||
|
t.Errorf("For test #%d, the call to the method worked, but it should not have.", testNumber)
|
||||||
|
t.Logf("WORKED: %t", worked)
|
||||||
|
t.Logf("OPTIONAL: (%T) %#v", test.Optional, test.Optional)
|
||||||
|
//////////////// CONTINUE
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,446 @@
|
||||||
|
package opt_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sourcecode.social/reiver/go-opt"
|
||||||
|
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestOptional_WhenSomething_string(t *testing.T) {
|
||||||
|
|
||||||
|
|
||||||
|
tests := []struct{
|
||||||
|
Optional interface{WhenSomething(func(string))}
|
||||||
|
Expected string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Optional: opt.Something[string](""),
|
||||||
|
Expected: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[string]("once twice thrice fource"),
|
||||||
|
Expected: "once twice thrice fource",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[string]("apple banana cherry"),
|
||||||
|
Expected: "apple banana cherry",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[string]("😈"),
|
||||||
|
Expected: "😈",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[string]("۰۱۲۳۴۵۶۷۸۹"),
|
||||||
|
Expected: "۰۱۲۳۴۵۶۷۸۹",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for testNumber, test := range tests {
|
||||||
|
|
||||||
|
var worked bool = false
|
||||||
|
var value string = "-<([-RaNdOmNeSs])>-"
|
||||||
|
|
||||||
|
test.Optional.WhenSomething(func(v string){
|
||||||
|
|
||||||
|
worked = true
|
||||||
|
value = v
|
||||||
|
})
|
||||||
|
|
||||||
|
if !worked {
|
||||||
|
t.Errorf("For test #%d, the call to the method did not seem work.", testNumber)
|
||||||
|
t.Logf("WORKED: %t", worked)
|
||||||
|
t.Logf("OPTIONAL: (%T) %#v", test.Optional, test.Optional)
|
||||||
|
/////////////// CONTINUE
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
expected := test.Expected
|
||||||
|
actual := value
|
||||||
|
|
||||||
|
if expected != actual {
|
||||||
|
t.Errorf("For test #%d, the actual value is not what was expected", testNumber)
|
||||||
|
t.Logf("EXPECTED: %q", expected)
|
||||||
|
t.Logf("EXPECTED: %q", actual)
|
||||||
|
t.Logf("WORKED: %t", worked)
|
||||||
|
/////////////////////// CONTINUE
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOptional_WhenSomething_stringNothing(t *testing.T) {
|
||||||
|
|
||||||
|
var worked bool = false
|
||||||
|
|
||||||
|
opt.Nothing[string]().WhenSomething(func(v string){
|
||||||
|
|
||||||
|
worked = true
|
||||||
|
})
|
||||||
|
|
||||||
|
if worked {
|
||||||
|
t.Errorf("The call to the method worked, but it should not have.")
|
||||||
|
t.Logf("WORKED: %t", worked)
|
||||||
|
//////////////// RETURN
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOptional_WhenSomething_int8(t *testing.T) {
|
||||||
|
|
||||||
|
|
||||||
|
tests := []struct{
|
||||||
|
Optional interface{WhenSomething(func(int8))}
|
||||||
|
Expected int8
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int8](-127),
|
||||||
|
Expected: -127,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int8](-126),
|
||||||
|
Expected: -126,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int8](-125),
|
||||||
|
Expected: -125,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int8](-124),
|
||||||
|
Expected: -124,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int8](-123),
|
||||||
|
Expected: -123,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int8](-122),
|
||||||
|
Expected: -122,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int8](-121),
|
||||||
|
Expected: -121,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int8](-120),
|
||||||
|
Expected: -120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int8](-9),
|
||||||
|
Expected: -9,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int8](-8),
|
||||||
|
Expected: -8,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int8](-7),
|
||||||
|
Expected: -7,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int8](-6),
|
||||||
|
Expected: -6,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int8](-5),
|
||||||
|
Expected: -5,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int8](-4),
|
||||||
|
Expected: -4,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int8](-3),
|
||||||
|
Expected: -3,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int8](-2),
|
||||||
|
Expected: -2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int8](-1),
|
||||||
|
Expected: -1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int8](0),
|
||||||
|
Expected: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int8](1),
|
||||||
|
Expected: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int8](2),
|
||||||
|
Expected: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int8](3),
|
||||||
|
Expected: 3,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int8](4),
|
||||||
|
Expected: 4,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int8](5),
|
||||||
|
Expected: 5,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int8](6),
|
||||||
|
Expected: 6,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int8](7),
|
||||||
|
Expected: 7,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int8](8),
|
||||||
|
Expected: 8,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int8](9),
|
||||||
|
Expected: 9,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int8](120),
|
||||||
|
Expected: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int8](121),
|
||||||
|
Expected: 121,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int8](122),
|
||||||
|
Expected: 122,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int8](123),
|
||||||
|
Expected: 123,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int8](124),
|
||||||
|
Expected: 124,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int8](125),
|
||||||
|
Expected: 125,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int8](126),
|
||||||
|
Expected: 126,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[int8](127),
|
||||||
|
Expected: 127,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for testNumber, test := range tests {
|
||||||
|
|
||||||
|
var worked bool = false
|
||||||
|
var value int8 = -101
|
||||||
|
|
||||||
|
test.Optional.WhenSomething(func(v int8){
|
||||||
|
|
||||||
|
worked = true
|
||||||
|
value = v
|
||||||
|
})
|
||||||
|
|
||||||
|
if !worked {
|
||||||
|
t.Errorf("For test #%d, the call to the method did not seem work.", testNumber)
|
||||||
|
t.Logf("WORKED: %t", worked)
|
||||||
|
t.Logf("OPTIONAL: (%T) %#v", test.Optional, test.Optional)
|
||||||
|
//////////////// CONTINUE
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
expected := test.Expected
|
||||||
|
actual := value
|
||||||
|
|
||||||
|
if expected != actual {
|
||||||
|
t.Errorf("For test #%d, the actual value is not what was expected", testNumber)
|
||||||
|
t.Logf("EXPECTED: %d", expected)
|
||||||
|
t.Logf("EXPECTED: %d", actual)
|
||||||
|
t.Logf("WORKED: %t", worked)
|
||||||
|
/////////////////////// CONTINUE
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOptional_WhenSomething_int8Nothing(t *testing.T) {
|
||||||
|
|
||||||
|
var worked bool = false
|
||||||
|
|
||||||
|
opt.Nothing[int8]().WhenSomething(func(v int8){
|
||||||
|
|
||||||
|
worked = true
|
||||||
|
})
|
||||||
|
|
||||||
|
if worked {
|
||||||
|
t.Errorf("The call to the method worked, but it should not have.")
|
||||||
|
t.Logf("WORKED: %t", worked)
|
||||||
|
//////////////// RETURN
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOptional_WhenSomething_uint8(t *testing.T) {
|
||||||
|
|
||||||
|
|
||||||
|
tests := []struct{
|
||||||
|
Optional interface{WhenSomething(func(uint8))}
|
||||||
|
Expected uint8
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Optional: opt.Something[uint8](0),
|
||||||
|
Expected: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[uint8](1),
|
||||||
|
Expected: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[uint8](2),
|
||||||
|
Expected: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[uint8](3),
|
||||||
|
Expected: 3,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[uint8](4),
|
||||||
|
Expected: 4,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[uint8](5),
|
||||||
|
Expected: 5,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[uint8](6),
|
||||||
|
Expected: 6,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[uint8](7),
|
||||||
|
Expected: 7,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[uint8](8),
|
||||||
|
Expected: 8,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[uint8](9),
|
||||||
|
Expected: 9,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[uint8](120),
|
||||||
|
Expected: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[uint8](121),
|
||||||
|
Expected: 121,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[uint8](122),
|
||||||
|
Expected: 122,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[uint8](123),
|
||||||
|
Expected: 123,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[uint8](124),
|
||||||
|
Expected: 124,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[uint8](125),
|
||||||
|
Expected: 125,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[uint8](126),
|
||||||
|
Expected: 126,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[uint8](127),
|
||||||
|
Expected: 127,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[uint8](250),
|
||||||
|
Expected: 250,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[uint8](251),
|
||||||
|
Expected: 251,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[uint8](252),
|
||||||
|
Expected: 252,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[uint8](253),
|
||||||
|
Expected: 253,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[uint8](254),
|
||||||
|
Expected: 254,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something[uint8](255),
|
||||||
|
Expected: 255,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for testNumber, test := range tests {
|
||||||
|
|
||||||
|
var worked bool = false
|
||||||
|
var value uint8 = 101
|
||||||
|
|
||||||
|
test.Optional.WhenSomething(func(v uint8){
|
||||||
|
|
||||||
|
worked = true
|
||||||
|
value = v
|
||||||
|
})
|
||||||
|
|
||||||
|
if !worked {
|
||||||
|
t.Errorf("For test #%d, the call to the method did not seem work.", testNumber)
|
||||||
|
t.Logf("WORKED: %t", worked)
|
||||||
|
t.Logf("OPTIONAL: (%T) %#v", test.Optional, test.Optional)
|
||||||
|
//////////////// CONTINUE
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
expected := test.Expected
|
||||||
|
actual := value
|
||||||
|
|
||||||
|
if expected != actual {
|
||||||
|
t.Errorf("For test #%d, the actual value is not what was expected", testNumber)
|
||||||
|
t.Logf("EXPECTED: %d", expected)
|
||||||
|
t.Logf("EXPECTED: %d", actual)
|
||||||
|
t.Logf("WORKED: %t", worked)
|
||||||
|
/////////////////////// CONTINUE
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOptional_WhenSomething_uint8Nothing(t *testing.T) {
|
||||||
|
|
||||||
|
var worked bool = false
|
||||||
|
|
||||||
|
opt.Nothing[uint8]().WhenSomething(func(v uint8){
|
||||||
|
|
||||||
|
worked = true
|
||||||
|
})
|
||||||
|
|
||||||
|
if worked {
|
||||||
|
t.Errorf("The call to the method worked, but it should not have.")
|
||||||
|
t.Logf("WORKED: %t", worked)
|
||||||
|
//////////////// RETURN
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,248 +0,0 @@
|
||||||
package optstring
|
|
||||||
|
|
||||||
/*
|
|
||||||
* CODE GENERATED AUTOMATICALLY WITH https://github.com/reiver/gogen-optiontype
|
|
||||||
* THIS FILE SHOULD NOT BE EDITED BY HAND
|
|
||||||
*/
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"database/sql/driver"
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
errNilReceiver = errors.New("Nil Receiver")
|
|
||||||
errNone = errors.New("optstring.None()")
|
|
||||||
errNoneNullable = errors.New("optstring.NoneNullable()")
|
|
||||||
errNull = errors.New("optstring.Null()")
|
|
||||||
)
|
|
||||||
|
|
||||||
func (receiver *NullableType) Scan(src interface{}) error {
|
|
||||||
if nil == receiver {
|
|
||||||
return errNilReceiver
|
|
||||||
}
|
|
||||||
|
|
||||||
if nil == src {
|
|
||||||
*receiver = Null()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
switch t := src.(type) {
|
|
||||||
case NullableType:
|
|
||||||
*receiver = t
|
|
||||||
return nil
|
|
||||||
case Type:
|
|
||||||
switch t {
|
|
||||||
case None():
|
|
||||||
*receiver = NoneNullable()
|
|
||||||
default:
|
|
||||||
datum, err := t.String()
|
|
||||||
if nil != err {
|
|
||||||
return fmt.Errorf("Problem unwrapping %T: (%T) %v", t, err, err)
|
|
||||||
}
|
|
||||||
*receiver = SomeNullable(datum)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
case string:
|
|
||||||
*receiver = SomeNullable(t)
|
|
||||||
return nil
|
|
||||||
case []byte:
|
|
||||||
s := string(t)
|
|
||||||
*receiver = SomeNullable(s)
|
|
||||||
return nil
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("Cannot scan something of type %T into an %T.", src, *receiver)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (receiver NullableType) String() (string, error) {
|
|
||||||
if NoneNullable() == receiver {
|
|
||||||
return "", errNoneNullable
|
|
||||||
}
|
|
||||||
if Null() == receiver {
|
|
||||||
return "", errNull
|
|
||||||
}
|
|
||||||
|
|
||||||
return receiver.value, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type NullableType struct {
|
|
||||||
loaded bool
|
|
||||||
null bool
|
|
||||||
value string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (receiver NullableType) MarshalJSON() ([]byte, error) {
|
|
||||||
if NoneNullable() == receiver {
|
|
||||||
return nil, errNoneNullable
|
|
||||||
}
|
|
||||||
if Null() == receiver {
|
|
||||||
return json.Marshal(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
return json.Marshal(receiver.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (receiver NullableType) WhenNone(fn func()) {
|
|
||||||
if NoneNullable() == receiver {
|
|
||||||
fn()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (receiver NullableType) WhenNull(fn func()) {
|
|
||||||
if Null() == receiver {
|
|
||||||
fn()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (receiver NullableType) WhenSome(fn func(string)) {
|
|
||||||
if NoneNullable() != receiver && Null() != receiver {
|
|
||||||
fn(receiver.value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (receiver *NullableType) UnmarshalJSON(b []byte) error {
|
|
||||||
if nil == receiver {
|
|
||||||
return errNilReceiver
|
|
||||||
}
|
|
||||||
|
|
||||||
if 0 == bytes.Compare(b, []byte{'n','u','l','l'}) {
|
|
||||||
*receiver = Null()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var target string
|
|
||||||
|
|
||||||
if err := json.Unmarshal(b, &target); nil != err {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
*receiver = SomeNullable(target)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (receiver NullableType) Value() (driver.Value, error) {
|
|
||||||
if NoneNullable() == receiver {
|
|
||||||
return nil, errNoneNullable
|
|
||||||
}
|
|
||||||
if Null() == receiver {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return receiver.value, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func NoneNullable() NullableType {
|
|
||||||
return NullableType{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func SomeNullable(value string) NullableType {
|
|
||||||
return NullableType{
|
|
||||||
value: value,
|
|
||||||
loaded: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Null() NullableType {
|
|
||||||
return NullableType{
|
|
||||||
null: true,
|
|
||||||
loaded: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (receiver *Type) Scan(src interface{}) error {
|
|
||||||
if nil == receiver {
|
|
||||||
return errNilReceiver
|
|
||||||
}
|
|
||||||
|
|
||||||
switch t := src.(type) {
|
|
||||||
case Type:
|
|
||||||
*receiver = t
|
|
||||||
return nil
|
|
||||||
case string:
|
|
||||||
*receiver = Some(t)
|
|
||||||
return nil
|
|
||||||
case []byte:
|
|
||||||
s := string(t)
|
|
||||||
*receiver = Some(s)
|
|
||||||
return nil
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("Cannot scan something of type %T into an %T.", src, *receiver)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (receiver Type) String() (string, error) {
|
|
||||||
if None() == receiver {
|
|
||||||
return "", errNone
|
|
||||||
}
|
|
||||||
|
|
||||||
return receiver.value, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type Type struct {
|
|
||||||
loaded bool
|
|
||||||
value string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (receiver Type) MarshalJSON() ([]byte, error) {
|
|
||||||
if None() == receiver {
|
|
||||||
return nil, errNone
|
|
||||||
}
|
|
||||||
|
|
||||||
return json.Marshal(receiver.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (receiver *Type) UnmarshalJSON(b []byte) error {
|
|
||||||
if nil == receiver {
|
|
||||||
return errNilReceiver
|
|
||||||
}
|
|
||||||
|
|
||||||
if 0 == bytes.Compare(b, []byte{'n','u','l','l'}) {
|
|
||||||
return fmt.Errorf("Cannot unmarshal %q into %T.", string(b), *receiver)
|
|
||||||
}
|
|
||||||
|
|
||||||
var target string
|
|
||||||
|
|
||||||
if err := json.Unmarshal(b, &target); nil != err {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
*receiver = Some(target)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (receiver Type) WhenNone(fn func()) {
|
|
||||||
if None() == receiver {
|
|
||||||
fn()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (receiver Type) WhenSome(fn func(string)) {
|
|
||||||
if None() != receiver {
|
|
||||||
fn(receiver.value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (receiver Type) Value() (driver.Value, error) {
|
|
||||||
if None() == receiver {
|
|
||||||
return nil, errNone
|
|
||||||
}
|
|
||||||
|
|
||||||
return receiver.value, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func None() Type {
|
|
||||||
return Type{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Some(value string) Type {
|
|
||||||
return Type{
|
|
||||||
value: value,
|
|
||||||
loaded: true,
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
package optstring
|
|
||||||
|
|
||||||
//go:generate gogen-optiontype --pkg=optstring --type=string --one-file --no-tests
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
package opt
|
||||||
|
|
||||||
|
// Then applies the function ‘fn’ to the value inside of the optional-type ‘op’, if the optional-type ‘op’ is holding something, and returns the resulting optional-type.
|
||||||
|
// If the optional-type ‘op’ is holding nothing, then Then also returns nothing.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
//
|
||||||
|
// fn := func(s string) opt.Optional[byte] {
|
||||||
|
//
|
||||||
|
// if len(s) < 2 {
|
||||||
|
// return opt.Nothing[byte]()
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return opt.Something[byte](s[1])
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// var op opt.Optional[string] = opt.Something("Hello world!"")
|
||||||
|
//
|
||||||
|
// var result opt.Optional[byte] = opt.Then(op, fn)
|
||||||
|
//
|
||||||
|
// // result == opt.Something[byte]('e')
|
||||||
|
//
|
||||||
|
// // ...
|
||||||
|
//
|
||||||
|
// var op2 opt.Optional[string] = opt.Something[string]("X")
|
||||||
|
//
|
||||||
|
// var result2 opt.Optional[byte] = opt.Then(op, fn)
|
||||||
|
//
|
||||||
|
// // result2 == opt.Nothing[byte]()
|
||||||
|
//
|
||||||
|
// // ...
|
||||||
|
//
|
||||||
|
// var op2 opt.Optional[string] = opt.Nothing[string]()
|
||||||
|
//
|
||||||
|
// var result2 opt.Optional[byte] = opt.Then(op, fn)
|
||||||
|
//
|
||||||
|
// // result2 == opt.Nothing[byte]()
|
||||||
|
func Then[T1 any, T2 any](op Optional[T1], fn func(T1)Optional[T2]) Optional[T2] {
|
||||||
|
if !op.something {
|
||||||
|
return Nothing[T2]()
|
||||||
|
}
|
||||||
|
|
||||||
|
return fn(op.value)
|
||||||
|
}
|
|
@ -0,0 +1,88 @@
|
||||||
|
package opt_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sourcecode.social/reiver/go-opt"
|
||||||
|
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestThen_stringToUint(t *testing.T) {
|
||||||
|
|
||||||
|
tests := []struct{
|
||||||
|
Optional opt.Optional[string]
|
||||||
|
Expected opt.Optional[byte]
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Optional: opt.Nothing[string](),
|
||||||
|
Expected: opt.Nothing[byte](),
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
Optional: opt.Something(""),
|
||||||
|
Expected: opt.Nothing[byte](),
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
Optional: opt.Something("A"),
|
||||||
|
Expected: opt.Nothing[byte](),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something("B"),
|
||||||
|
Expected: opt.Nothing[byte](),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something("C"),
|
||||||
|
Expected: opt.Nothing[byte](),
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
Optional: opt.Something("once"),
|
||||||
|
Expected: opt.Something[byte]('n'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something("twice"),
|
||||||
|
Expected: opt.Something[byte]('w'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something("thrice"),
|
||||||
|
Expected: opt.Something[byte]('h'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Optional: opt.Something("fource"),
|
||||||
|
Expected: opt.Something[byte]('o'),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for testNumber, test := range tests {
|
||||||
|
|
||||||
|
fn := func(s string) opt.Optional[byte] {
|
||||||
|
if len(s) < 2 {
|
||||||
|
return opt.Nothing[byte]()
|
||||||
|
}
|
||||||
|
|
||||||
|
return opt.Something[byte](s[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
thened := opt.Then(test.Optional, fn)
|
||||||
|
|
||||||
|
{
|
||||||
|
expected := test.Expected
|
||||||
|
actual := thened
|
||||||
|
|
||||||
|
if expected != actual {
|
||||||
|
t.Errorf("For test #%d, the actual value is not what was expected.", testNumber)
|
||||||
|
t.Logf("EXPECTED: (%T) %#v", expected, expected)
|
||||||
|
t.Logf("ACTUAL: (%T) %#v", actual, actual)
|
||||||
|
t.Logf("OPTIONAL: (%T), %#v", test.Optional, test.Optional)
|
||||||
|
/////////////////////// CONTINUE
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue