Browse code

Add builtin nodes discovery

Use `pkg/discovery` to provide nodes discovery between daemon instances.

The functionality is driven by two different command-line flags: the
experimental `--cluster-store` (previously `--kv-store`) and
`--cluster-advertise`. It can be used in two ways by interested
components:

1. Externally by calling the `/info` API and examining the cluster store
field. The `pkg/discovery` package can then be used to hit the same
endpoint and watch for appearing or disappearing nodes. That is the
method that will for example be used by Swarm.
2. Internally by using the `Daemon.discoveryWatcher` instance. That is
the method that will for example be used by libnetwork.

Signed-off-by: Arnaud Porterie <arnaud.porterie@docker.com>

Arnaud Porterie authored on 2015/09/11 08:12:00
Showing 35 changed files
... ...
@@ -103,6 +103,9 @@ func (cli *DockerCli) CmdInfo(args ...string) error {
103 103
 	}
104 104
 
105 105
 	ioutils.FprintfIfTrue(cli.out, "Experimental: %v\n", info.ExperimentalBuild)
106
+	if info.ClusterStore != "" {
107
+		fmt.Fprintf(cli.out, "Cluster store: %s\n", info.ClusterStore)
108
+	}
106 109
 
107 110
 	return nil
108 111
 }
... ...
@@ -216,6 +216,7 @@ type Info struct {
216 216
 	Labels             []string
217 217
 	ExperimentalBuild  bool
218 218
 	ServerVersion      string
219
+	ClusterStore       string
219 220
 }
220 221
 
221 222
 // ExecStartCheck is a temp struct used by execStart
... ...
@@ -33,7 +33,16 @@ type CommonConfig struct {
33 33
 	Root           string
34 34
 	TrustKeyPath   string
35 35
 	DefaultNetwork string
36
-	NetworkKVStore string
36
+
37
+	// ClusterStore is the storage backend used for the cluster information. It is used by both
38
+	// multihost networking (to store networks and endpoints information) and by the node discovery
39
+	// mechanism.
40
+	ClusterStore string
41
+
42
+	// ClusterAdvertise is the network endpoint that the Engine advertises for the purpose of node
43
+	// discovery. This should be a 'host:port' combination on which that daemon instance is
44
+	// reachable by other hosts.
45
+	ClusterAdvertise string
37 46
 }
38 47
 
39 48
 // InstallCommonFlags adds command-line options to the top-level flag parser for
... ...
@@ -57,4 +66,6 @@ func (config *Config) InstallCommonFlags(cmd *flag.FlagSet, usageFn func(string)
57 57
 	cmd.Var(opts.NewListOptsRef(&config.Labels, opts.ValidateLabel), []string{"-label"}, usageFn("Set key=value labels to the daemon"))
58 58
 	cmd.StringVar(&config.LogConfig.Type, []string{"-log-driver"}, "json-file", usageFn("Default driver for container logs"))
59 59
 	cmd.Var(opts.NewMapOpts(config.LogConfig.Config, nil), []string{"-log-opt"}, usageFn("Set log driver options"))
60
+	cmd.StringVar(&config.ClusterAdvertise, []string{"-cluster-advertise"}, "", usageFn("Address of the daemon instance to advertise"))
61
+	cmd.StringVar(&config.ClusterStore, []string{"-cluster-store"}, "", usageFn("Set the cluster store"))
60 62
 }
... ...
@@ -6,5 +6,4 @@ import flag "github.com/docker/docker/pkg/mflag"
6 6
 
7 7
 func (config *Config) attachExperimentalFlags(cmd *flag.FlagSet, usageFn func(string) string) {
8 8
 	cmd.StringVar(&config.DefaultNetwork, []string{"-default-network"}, "", usageFn("Set default network"))
9
-	cmd.StringVar(&config.NetworkKVStore, []string{"-kv-store"}, "", usageFn("Set KV Store configuration"))
10 9
 }
... ...
@@ -34,6 +34,7 @@ import (
34 34
 	"github.com/docker/docker/image"
35 35
 	"github.com/docker/docker/pkg/archive"
36 36
 	"github.com/docker/docker/pkg/broadcastwriter"
37
+	"github.com/docker/docker/pkg/discovery"
37 38
 	"github.com/docker/docker/pkg/fileutils"
38 39
 	"github.com/docker/docker/pkg/graphdb"
39 40
 	"github.com/docker/docker/pkg/ioutils"
... ...
@@ -116,6 +117,7 @@ type Daemon struct {
116 116
 	EventsService    *events.Events
117 117
 	netController    libnetwork.NetworkController
118 118
 	volumes          *store.VolumeStore
119
+	discoveryWatcher discovery.Watcher
119 120
 	root             string
120 121
 	shutdown         bool
121 122
 }
... ...
@@ -751,6 +753,16 @@ func NewDaemon(config *Config, registryService *registry.Service) (daemon *Daemo
751 751
 		return nil, err
752 752
 	}
753 753
 
754
+	// Discovery is only enabled when the daemon is launched with an address to advertise.  When
755
+	// initialized, the daemon is registered and we can store the discovery backend as its read-only
756
+	// DiscoveryWatcher version.
757
+	if config.ClusterStore != "" && config.ClusterAdvertise != "" {
758
+		var err error
759
+		if d.discoveryWatcher, err = initDiscovery(config.ClusterStore, config.ClusterAdvertise); err != nil {
760
+			return nil, fmt.Errorf("discovery initialization failed (%v)", err)
761
+		}
762
+	}
763
+
754 764
 	d.ID = trustKey.PublicKey().KeyID()
755 765
 	d.repository = daemonRepo
756 766
 	d.containers = &contStore{s: make(map[string]*Container)}
... ...
@@ -312,8 +312,8 @@ func networkOptions(dconfig *Config) ([]nwconfig.Option, error) {
312 312
 		options = append(options, nwconfig.OptionDefaultNetwork(dn))
313 313
 	}
314 314
 
315
-	if strings.TrimSpace(dconfig.NetworkKVStore) != "" {
316
-		kv := strings.Split(dconfig.NetworkKVStore, "://")
315
+	if strings.TrimSpace(dconfig.ClusterStore) != "" {
316
+		kv := strings.Split(dconfig.ClusterStore, "://")
317 317
 		if len(kv) < 2 {
318 318
 			return nil, fmt.Errorf("kv store daemon config must be of the form KV-PROVIDER://KV-URL")
319 319
 		}
320 320
new file mode 100644
... ...
@@ -0,0 +1,48 @@
0
+package daemon
1
+
2
+import (
3
+	"time"
4
+
5
+	log "github.com/Sirupsen/logrus"
6
+	"github.com/docker/docker/pkg/discovery"
7
+
8
+	// Register the libkv backends for discovery.
9
+	_ "github.com/docker/docker/pkg/discovery/kv"
10
+)
11
+
12
+const (
13
+	// defaultDiscoveryHeartbeat is the default value for discovery heartbeat interval.
14
+	defaultDiscoveryHeartbeat = 20 * time.Second
15
+
16
+	// defaultDiscoveryTTL is the default TTL interface for discovery.
17
+	defaultDiscoveryTTL = 60 * time.Second
18
+)
19
+
20
+// initDiscovery initialized the nodes discovery subsystem by connecting to the specified backend
21
+// and start a registration loop to advertise the current node under the specified address.
22
+func initDiscovery(backend, address string) (discovery.Backend, error) {
23
+	var (
24
+		discoveryBackend discovery.Backend
25
+		err              error
26
+	)
27
+	if discoveryBackend, err = discovery.New(backend, defaultDiscoveryHeartbeat, defaultDiscoveryTTL); err != nil {
28
+		return nil, err
29
+	}
30
+
31
+	// We call Register() on the discovery backend in a loop for the whole lifetime of the daemon,
32
+	// but we never actually Watch() for nodes appearing and disappearing for the moment.
33
+	go registrationLoop(discoveryBackend, address)
34
+	return discoveryBackend, nil
35
+}
36
+
37
+// registrationLoop registers the current node against the discovery backend using the specified
38
+// address. The function never returns, as registration against the backend comes with a TTL and
39
+// requires regular heartbeats.
40
+func registrationLoop(discoveryBackend discovery.Backend, address string) {
41
+	for {
42
+		if err := discoveryBackend.Register(address); err != nil {
43
+			log.Errorf("Registering as %q in discovery failed: %v", address, err)
44
+		}
45
+		time.Sleep(defaultDiscoveryHeartbeat)
46
+	}
47
+}
... ...
@@ -92,6 +92,7 @@ func (daemon *Daemon) SystemInfo(ctx context.Context) (*types.Info, error) {
92 92
 		Labels:             daemon.config().Labels,
93 93
 		ExperimentalBuild:  utils.ExperimentalBuild(),
94 94
 		ServerVersion:      dockerversion.VERSION,
95
+		ClusterStore:       daemon.config().ClusterStore,
95 96
 	}
96 97
 
97 98
 	// TODO Windows. Refactor this more once sysinfo is refactored into
... ...
@@ -1821,6 +1821,7 @@ Display system-wide information
1821 1821
         "CpuCfsPeriod": true,
1822 1822
         "CpuCfsQuota": true,
1823 1823
         "Debug": false,
1824
+        "DiscoveryBackend": "etcd://localhost:2379",
1824 1825
         "DockerRootDir": "/var/lib/docker",
1825 1826
         "Driver": "btrfs",
1826 1827
         "DriverStatus": [[""]],
... ...
@@ -22,6 +22,8 @@ weight=1
22 22
       -D, --debug=false                      Enable debug mode
23 23
       --default-gateway=""                   Container default gateway IPv4 address
24 24
       --default-gateway-v6=""                Container default gateway IPv6 address
25
+      --cluster-store=""                     URL of the distributed storage backend
26
+      --cluster-advertise=""                 Address of the daemon instance to advertise
25 27
       --dns=[]                               DNS server to use
26 28
       --dns-opt=[]                           DNS options to use
27 29
       --dns-search=[]                        DNS search domains to use
... ...
@@ -484,6 +486,12 @@ Be careful setting `nproc` with the `ulimit` flag as `nproc` is designed by Linu
484 484
 set the maximum number of processes available to a user, not to a container. For details
485 485
 please check the [run](run.md) reference.
486 486
 
487
+## Nodes discovery
488
+
489
+`--cluster-advertise` specifies the 'host:port' combination that this particular
490
+daemon instance should use when advertising itself to the cluster. The daemon
491
+should be reachable by remote hosts on this 'host:port' combination.
492
+
487 493
 ## Miscellaneous options
488 494
 
489 495
 IP masquerading uses address translation to allow containers without a public
... ...
@@ -5,10 +5,10 @@ Using the above experimental UI `docker network`, `docker service` and `--publis
5 5
 
6 6
 Since `network` and `service` objects are globally significant, this feature requires distributed states provided by the `libkv` project.
7 7
 Using `libkv`, the user can plug any of the supported Key-Value store (such as consul, etcd or zookeeper).
8
-User can specify the Key-Value store of choice using the `--kv-store` daemon flag, which takes configuration value of format `PROVIDER:URL`, where
8
+User can specify the Key-Value store of choice using the `--cluster-store` daemon flag, which takes configuration value of format `PROVIDER:URL`, where
9 9
 `PROVIDER` is the name of the Key-Value store (such as consul, etcd or zookeeper) and
10 10
 `URL` is the url to reach the Key-Value store.
11
-Example : `docker daemon --kv-store=consul:localhost:8500`
11
+Example : `docker daemon --cluster-store=consul://localhost:8500`
12 12
 
13 13
 Send us feedback and comments on [#14083](https://github.com/docker/docker/issues/14083)
14 14
 or on the usual Google Groups (docker-user, docker-dev) and IRC channels.
... ...
@@ -108,6 +108,8 @@ clean() {
108 108
 	findArgs=(
109 109
 		# This directory contains only .c and .h files which are necessary
110 110
 		-path vendor/src/github.com/mattn/go-sqlite3/code
111
+		# This directory is needed for compiling the unit tests
112
+		-o -path vendor/src/github.com/stretchr/objx
111 113
 	)
112 114
 	for import in "${imports[@]}"; do
113 115
 		[ "${#findArgs[@]}" -eq 0 ] || findArgs+=( -or )
... ...
@@ -16,6 +16,7 @@ clone git github.com/kr/pty 5cf931ef8f
16 16
 clone git github.com/mattn/go-sqlite3 v1.1.0
17 17
 clone git github.com/microsoft/hcsshim 7f646aa6b26bcf90caee91e93cde4a80d0d8a83e
18 18
 clone git github.com/mistifyio/go-zfs v2.1.1
19
+clone git github.com/stretchr/objx cbeaeb16a013161a98496fad62933b1d21786672
19 20
 clone git github.com/stretchr/testify 7c2b1e5640dcf2631213ca962d892bffa1e08860
20 21
 clone git github.com/tchap/go-patricia v2.1.0
21 22
 clone git golang.org/x/net 3cffabab72adf04f8e3b01c5baf775361837b5fe https://github.com/golang/net.git
... ...
@@ -1,8 +1,10 @@
1 1
 package main
2 2
 
3 3
 import (
4
+	"fmt"
4 5
 	"strings"
5 6
 
7
+	"github.com/docker/docker/pkg/integration/checker"
6 8
 	"github.com/docker/docker/utils"
7 9
 	"github.com/go-check/check"
8 10
 )
... ...
@@ -35,3 +37,20 @@ func (s *DockerSuite) TestInfoEnsureSucceeds(c *check.C) {
35 35
 		}
36 36
 	}
37 37
 }
38
+
39
+// TestInfoDiscoveryBackend verifies that a daemon run with `--cluster-advertise` and
40
+// `--cluster-store` properly show the backend's endpoint in info output.
41
+func (s *DockerSuite) TestInfoDiscoveryBackend(c *check.C) {
42
+	testRequires(c, SameHostDaemon)
43
+
44
+	d := NewDaemon(c)
45
+	discoveryBackend := "consul://consuladdr:consulport/some/path"
46
+	if err := d.Start(fmt.Sprintf("--cluster-store=%s", discoveryBackend), "--cluster-advertise=foo"); err != nil {
47
+		c.Fatal(err)
48
+	}
49
+	defer d.Stop()
50
+
51
+	out, err := d.Cmd("info")
52
+	c.Assert(err, checker.IsNil)
53
+	c.Assert(out, checker.Contains, fmt.Sprintf("Cluster store: %s\n", discoveryBackend))
54
+}
38 55
new file mode 100644
... ...
@@ -0,0 +1,113 @@
0
+package mock
1
+
2
+import (
3
+	"github.com/docker/libkv/store"
4
+	"github.com/stretchr/testify/mock"
5
+)
6
+
7
+// Mock store. Mocks all Store functions using testify.Mock
8
+type Mock struct {
9
+	mock.Mock
10
+
11
+	// Endpoints passed to InitializeMock
12
+	Endpoints []string
13
+
14
+	// Options passed to InitializeMock
15
+	Options *store.Config
16
+}
17
+
18
+// New creates a Mock store
19
+func New(endpoints []string, options *store.Config) (store.Store, error) {
20
+	s := &Mock{}
21
+	s.Endpoints = endpoints
22
+	s.Options = options
23
+	return s, nil
24
+}
25
+
26
+// Put mock
27
+func (s *Mock) Put(key string, value []byte, opts *store.WriteOptions) error {
28
+	args := s.Mock.Called(key, value, opts)
29
+	return args.Error(0)
30
+}
31
+
32
+// Get mock
33
+func (s *Mock) Get(key string) (*store.KVPair, error) {
34
+	args := s.Mock.Called(key)
35
+	return args.Get(0).(*store.KVPair), args.Error(1)
36
+}
37
+
38
+// Delete mock
39
+func (s *Mock) Delete(key string) error {
40
+	args := s.Mock.Called(key)
41
+	return args.Error(0)
42
+}
43
+
44
+// Exists mock
45
+func (s *Mock) Exists(key string) (bool, error) {
46
+	args := s.Mock.Called(key)
47
+	return args.Bool(0), args.Error(1)
48
+}
49
+
50
+// Watch mock
51
+func (s *Mock) Watch(key string, stopCh <-chan struct{}) (<-chan *store.KVPair, error) {
52
+	args := s.Mock.Called(key, stopCh)
53
+	return args.Get(0).(<-chan *store.KVPair), args.Error(1)
54
+}
55
+
56
+// WatchTree mock
57
+func (s *Mock) WatchTree(prefix string, stopCh <-chan struct{}) (<-chan []*store.KVPair, error) {
58
+	args := s.Mock.Called(prefix, stopCh)
59
+	return args.Get(0).(chan []*store.KVPair), args.Error(1)
60
+}
61
+
62
+// NewLock mock
63
+func (s *Mock) NewLock(key string, options *store.LockOptions) (store.Locker, error) {
64
+	args := s.Mock.Called(key, options)
65
+	return args.Get(0).(store.Locker), args.Error(1)
66
+}
67
+
68
+// List mock
69
+func (s *Mock) List(prefix string) ([]*store.KVPair, error) {
70
+	args := s.Mock.Called(prefix)
71
+	return args.Get(0).([]*store.KVPair), args.Error(1)
72
+}
73
+
74
+// DeleteTree mock
75
+func (s *Mock) DeleteTree(prefix string) error {
76
+	args := s.Mock.Called(prefix)
77
+	return args.Error(0)
78
+}
79
+
80
+// AtomicPut mock
81
+func (s *Mock) AtomicPut(key string, value []byte, previous *store.KVPair, opts *store.WriteOptions) (bool, *store.KVPair, error) {
82
+	args := s.Mock.Called(key, value, previous, opts)
83
+	return args.Bool(0), args.Get(1).(*store.KVPair), args.Error(2)
84
+}
85
+
86
+// AtomicDelete mock
87
+func (s *Mock) AtomicDelete(key string, previous *store.KVPair) (bool, error) {
88
+	args := s.Mock.Called(key, previous)
89
+	return args.Bool(0), args.Error(1)
90
+}
91
+
92
+// Lock mock implementation of Locker
93
+type Lock struct {
94
+	mock.Mock
95
+}
96
+
97
+// Lock mock
98
+func (l *Lock) Lock() (<-chan struct{}, error) {
99
+	args := l.Mock.Called()
100
+	return args.Get(0).(<-chan struct{}), args.Error(1)
101
+}
102
+
103
+// Unlock mock
104
+func (l *Lock) Unlock() error {
105
+	args := l.Mock.Called()
106
+	return args.Error(0)
107
+}
108
+
109
+// Close mock
110
+func (s *Mock) Close() {
111
+	return
112
+}
0 113
new file mode 100644
... ...
@@ -0,0 +1,22 @@
0
+# Compiled Object files, Static and Dynamic libs (Shared Objects)
1
+*.o
2
+*.a
3
+*.so
4
+
5
+# Folders
6
+_obj
7
+_test
8
+
9
+# Architecture specific extensions/prefixes
10
+*.[568vq]
11
+[568vq].out
12
+
13
+*.cgo1.go
14
+*.cgo2.c
15
+_cgo_defun.c
16
+_cgo_gotypes.go
17
+_cgo_export.*
18
+
19
+_testmain.go
20
+
21
+*.exe
0 22
new file mode 100644
... ...
@@ -0,0 +1,23 @@
0
+objx - by Mat Ryer and Tyler Bunnell
1
+
2
+The MIT License (MIT)
3
+
4
+Copyright (c) 2014 Stretchr, Inc.
5
+
6
+Permission is hereby granted, free of charge, to any person obtaining a copy
7
+of this software and associated documentation files (the "Software"), to deal
8
+in the Software without restriction, including without limitation the rights
9
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+copies of the Software, and to permit persons to whom the Software is
11
+furnished to do so, subject to the following conditions:
12
+
13
+The above copyright notice and this permission notice shall be included in all
14
+copies or substantial portions of the Software.
15
+
16
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+SOFTWARE.
0 23
new file mode 100644
... ...
@@ -0,0 +1,3 @@
0
+# objx
1
+
2
+  * Jump into the [API Documentation](http://godoc.org/github.com/stretchr/objx)
0 3
new file mode 100644
... ...
@@ -0,0 +1,179 @@
0
+package objx
1
+
2
+import (
3
+	"fmt"
4
+	"regexp"
5
+	"strconv"
6
+	"strings"
7
+)
8
+
9
+// arrayAccesRegexString is the regex used to extract the array number
10
+// from the access path
11
+const arrayAccesRegexString = `^(.+)\[([0-9]+)\]$`
12
+
13
+// arrayAccesRegex is the compiled arrayAccesRegexString
14
+var arrayAccesRegex = regexp.MustCompile(arrayAccesRegexString)
15
+
16
+// Get gets the value using the specified selector and
17
+// returns it inside a new Obj object.
18
+//
19
+// If it cannot find the value, Get will return a nil
20
+// value inside an instance of Obj.
21
+//
22
+// Get can only operate directly on map[string]interface{} and []interface.
23
+//
24
+// Example
25
+//
26
+// To access the title of the third chapter of the second book, do:
27
+//
28
+//    o.Get("books[1].chapters[2].title")
29
+func (m Map) Get(selector string) *Value {
30
+	rawObj := access(m, selector, nil, false, false)
31
+	return &Value{data: rawObj}
32
+}
33
+
34
+// Set sets the value using the specified selector and
35
+// returns the object on which Set was called.
36
+//
37
+// Set can only operate directly on map[string]interface{} and []interface
38
+//
39
+// Example
40
+//
41
+// To set the title of the third chapter of the second book, do:
42
+//
43
+//    o.Set("books[1].chapters[2].title","Time to Go")
44
+func (m Map) Set(selector string, value interface{}) Map {
45
+	access(m, selector, value, true, false)
46
+	return m
47
+}
48
+
49
+// access accesses the object using the selector and performs the
50
+// appropriate action.
51
+func access(current, selector, value interface{}, isSet, panics bool) interface{} {
52
+
53
+	switch selector.(type) {
54
+	case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
55
+
56
+		if array, ok := current.([]interface{}); ok {
57
+			index := intFromInterface(selector)
58
+
59
+			if index >= len(array) {
60
+				if panics {
61
+					panic(fmt.Sprintf("objx: Index %d is out of range. Slice only contains %d items.", index, len(array)))
62
+				}
63
+				return nil
64
+			}
65
+
66
+			return array[index]
67
+		}
68
+
69
+		return nil
70
+
71
+	case string:
72
+
73
+		selStr := selector.(string)
74
+		selSegs := strings.SplitN(selStr, PathSeparator, 2)
75
+		thisSel := selSegs[0]
76
+		index := -1
77
+		var err error
78
+
79
+		// https://github.com/stretchr/objx/issues/12
80
+		if strings.Contains(thisSel, "[") {
81
+
82
+			arrayMatches := arrayAccesRegex.FindStringSubmatch(thisSel)
83
+
84
+			if len(arrayMatches) > 0 {
85
+
86
+				// Get the key into the map
87
+				thisSel = arrayMatches[1]
88
+
89
+				// Get the index into the array at the key
90
+				index, err = strconv.Atoi(arrayMatches[2])
91
+
92
+				if err != nil {
93
+					// This should never happen. If it does, something has gone
94
+					// seriously wrong. Panic.
95
+					panic("objx: Array index is not an integer.  Must use array[int].")
96
+				}
97
+
98
+			}
99
+		}
100
+
101
+		if curMap, ok := current.(Map); ok {
102
+			current = map[string]interface{}(curMap)
103
+		}
104
+
105
+		// get the object in question
106
+		switch current.(type) {
107
+		case map[string]interface{}:
108
+			curMSI := current.(map[string]interface{})
109
+			if len(selSegs) <= 1 && isSet {
110
+				curMSI[thisSel] = value
111
+				return nil
112
+			} else {
113
+				current = curMSI[thisSel]
114
+			}
115
+		default:
116
+			current = nil
117
+		}
118
+
119
+		if current == nil && panics {
120
+			panic(fmt.Sprintf("objx: '%v' invalid on object.", selector))
121
+		}
122
+
123
+		// do we need to access the item of an array?
124
+		if index > -1 {
125
+			if array, ok := current.([]interface{}); ok {
126
+				if index < len(array) {
127
+					current = array[index]
128
+				} else {
129
+					if panics {
130
+						panic(fmt.Sprintf("objx: Index %d is out of range. Slice only contains %d items.", index, len(array)))
131
+					}
132
+					current = nil
133
+				}
134
+			}
135
+		}
136
+
137
+		if len(selSegs) > 1 {
138
+			current = access(current, selSegs[1], value, isSet, panics)
139
+		}
140
+
141
+	}
142
+
143
+	return current
144
+
145
+}
146
+
147
+// intFromInterface converts an interface object to the largest
148
+// representation of an unsigned integer using a type switch and
149
+// assertions
150
+func intFromInterface(selector interface{}) int {
151
+	var value int
152
+	switch selector.(type) {
153
+	case int:
154
+		value = selector.(int)
155
+	case int8:
156
+		value = int(selector.(int8))
157
+	case int16:
158
+		value = int(selector.(int16))
159
+	case int32:
160
+		value = int(selector.(int32))
161
+	case int64:
162
+		value = int(selector.(int64))
163
+	case uint:
164
+		value = int(selector.(uint))
165
+	case uint8:
166
+		value = int(selector.(uint8))
167
+	case uint16:
168
+		value = int(selector.(uint16))
169
+	case uint32:
170
+		value = int(selector.(uint32))
171
+	case uint64:
172
+		value = int(selector.(uint64))
173
+	default:
174
+		panic("objx: array access argument is not an integer type (this should never happen)")
175
+	}
176
+
177
+	return value
178
+}
0 179
new file mode 100644
... ...
@@ -0,0 +1,13 @@
0
+package objx
1
+
2
+const (
3
+	// PathSeparator is the character used to separate the elements
4
+	// of the keypath.
5
+	//
6
+	// For example, `location.address.city`
7
+	PathSeparator string = "."
8
+
9
+	// SignatureSeparator is the character that is used to
10
+	// separate the Base64 string from the security signature.
11
+	SignatureSeparator = "_"
12
+)
0 13
new file mode 100644
... ...
@@ -0,0 +1,117 @@
0
+package objx
1
+
2
+import (
3
+	"bytes"
4
+	"encoding/base64"
5
+	"encoding/json"
6
+	"errors"
7
+	"fmt"
8
+	"net/url"
9
+)
10
+
11
+// JSON converts the contained object to a JSON string
12
+// representation
13
+func (m Map) JSON() (string, error) {
14
+
15
+	result, err := json.Marshal(m)
16
+
17
+	if err != nil {
18
+		err = errors.New("objx: JSON encode failed with: " + err.Error())
19
+	}
20
+
21
+	return string(result), err
22
+
23
+}
24
+
25
+// MustJSON converts the contained object to a JSON string
26
+// representation and panics if there is an error
27
+func (m Map) MustJSON() string {
28
+	result, err := m.JSON()
29
+	if err != nil {
30
+		panic(err.Error())
31
+	}
32
+	return result
33
+}
34
+
35
+// Base64 converts the contained object to a Base64 string
36
+// representation of the JSON string representation
37
+func (m Map) Base64() (string, error) {
38
+
39
+	var buf bytes.Buffer
40
+
41
+	jsonData, err := m.JSON()
42
+	if err != nil {
43
+		return "", err
44
+	}
45
+
46
+	encoder := base64.NewEncoder(base64.StdEncoding, &buf)
47
+	encoder.Write([]byte(jsonData))
48
+	encoder.Close()
49
+
50
+	return buf.String(), nil
51
+
52
+}
53
+
54
+// MustBase64 converts the contained object to a Base64 string
55
+// representation of the JSON string representation and panics
56
+// if there is an error
57
+func (m Map) MustBase64() string {
58
+	result, err := m.Base64()
59
+	if err != nil {
60
+		panic(err.Error())
61
+	}
62
+	return result
63
+}
64
+
65
+// SignedBase64 converts the contained object to a Base64 string
66
+// representation of the JSON string representation and signs it
67
+// using the provided key.
68
+func (m Map) SignedBase64(key string) (string, error) {
69
+
70
+	base64, err := m.Base64()
71
+	if err != nil {
72
+		return "", err
73
+	}
74
+
75
+	sig := HashWithKey(base64, key)
76
+
77
+	return base64 + SignatureSeparator + sig, nil
78
+
79
+}
80
+
81
+// MustSignedBase64 converts the contained object to a Base64 string
82
+// representation of the JSON string representation and signs it
83
+// using the provided key and panics if there is an error
84
+func (m Map) MustSignedBase64(key string) string {
85
+	result, err := m.SignedBase64(key)
86
+	if err != nil {
87
+		panic(err.Error())
88
+	}
89
+	return result
90
+}
91
+
92
+/*
93
+	URL Query
94
+	------------------------------------------------
95
+*/
96
+
97
+// URLValues creates a url.Values object from an Obj. This
98
+// function requires that the wrapped object be a map[string]interface{}
99
+func (m Map) URLValues() url.Values {
100
+
101
+	vals := make(url.Values)
102
+
103
+	for k, v := range m {
104
+		//TODO: can this be done without sprintf?
105
+		vals.Set(k, fmt.Sprintf("%v", v))
106
+	}
107
+
108
+	return vals
109
+}
110
+
111
+// URLQuery gets an encoded URL query representing the given
112
+// Obj. This function requires that the wrapped object be a
113
+// map[string]interface{}
114
+func (m Map) URLQuery() (string, error) {
115
+	return m.URLValues().Encode(), nil
116
+}
0 117
new file mode 100644
... ...
@@ -0,0 +1,72 @@
0
+// objx - Go package for dealing with maps, slices, JSON and other data.
1
+//
2
+// Overview
3
+//
4
+// Objx provides the `objx.Map` type, which is a `map[string]interface{}` that exposes
5
+// a powerful `Get` method (among others) that allows you to easily and quickly get
6
+// access to data within the map, without having to worry too much about type assertions,
7
+// missing data, default values etc.
8
+//
9
+// Pattern
10
+//
11
+// Objx uses a preditable pattern to make access data from within `map[string]interface{}'s
12
+// easy.
13
+//
14
+// Call one of the `objx.` functions to create your `objx.Map` to get going:
15
+//
16
+//     m, err := objx.FromJSON(json)
17
+//
18
+// NOTE: Any methods or functions with the `Must` prefix will panic if something goes wrong,
19
+// the rest will be optimistic and try to figure things out without panicking.
20
+//
21
+// Use `Get` to access the value you're interested in.  You can use dot and array
22
+// notation too:
23
+//
24
+//     m.Get("places[0].latlng")
25
+//
26
+// Once you have saught the `Value` you're interested in, you can use the `Is*` methods
27
+// to determine its type.
28
+//
29
+//     if m.Get("code").IsStr() { /* ... */ }
30
+//
31
+// Or you can just assume the type, and use one of the strong type methods to
32
+// extract the real value:
33
+//
34
+//     m.Get("code").Int()
35
+//
36
+// If there's no value there (or if it's the wrong type) then a default value
37
+// will be returned, or you can be explicit about the default value.
38
+//
39
+//     Get("code").Int(-1)
40
+//
41
+// If you're dealing with a slice of data as a value, Objx provides many useful
42
+// methods for iterating, manipulating and selecting that data.  You can find out more
43
+// by exploring the index below.
44
+//
45
+// Reading data
46
+//
47
+// A simple example of how to use Objx:
48
+//
49
+//     // use MustFromJSON to make an objx.Map from some JSON
50
+//     m := objx.MustFromJSON(`{"name": "Mat", "age": 30}`)
51
+//
52
+//     // get the details
53
+//     name := m.Get("name").Str()
54
+//     age := m.Get("age").Int()
55
+//
56
+//     // get their nickname (or use their name if they
57
+//     // don't have one)
58
+//     nickname := m.Get("nickname").Str(name)
59
+//
60
+// Ranging
61
+//
62
+// Since `objx.Map` is a `map[string]interface{}` you can treat it as such.  For
63
+// example, to `range` the data, do what you would expect:
64
+//
65
+//     m := objx.MustFromJSON(json)
66
+//     for key, value := range m {
67
+//
68
+//       /* ... do your magic ... */
69
+//
70
+//     }
71
+package objx
0 72
new file mode 100644
... ...
@@ -0,0 +1,222 @@
0
+package objx
1
+
2
+import (
3
+	"encoding/base64"
4
+	"encoding/json"
5
+	"errors"
6
+	"io/ioutil"
7
+	"net/url"
8
+	"strings"
9
+)
10
+
11
+// MSIConvertable is an interface that defines methods for converting your
12
+// custom types to a map[string]interface{} representation.
13
+type MSIConvertable interface {
14
+	// MSI gets a map[string]interface{} (msi) representing the
15
+	// object.
16
+	MSI() map[string]interface{}
17
+}
18
+
19
+// Map provides extended functionality for working with
20
+// untyped data, in particular map[string]interface (msi).
21
+type Map map[string]interface{}
22
+
23
+// Value returns the internal value instance
24
+func (m Map) Value() *Value {
25
+	return &Value{data: m}
26
+}
27
+
28
+// Nil represents a nil Map.
29
+var Nil Map = New(nil)
30
+
31
+// New creates a new Map containing the map[string]interface{} in the data argument.
32
+// If the data argument is not a map[string]interface, New attempts to call the
33
+// MSI() method on the MSIConvertable interface to create one.
34
+func New(data interface{}) Map {
35
+	if _, ok := data.(map[string]interface{}); !ok {
36
+		if converter, ok := data.(MSIConvertable); ok {
37
+			data = converter.MSI()
38
+		} else {
39
+			return nil
40
+		}
41
+	}
42
+	return Map(data.(map[string]interface{}))
43
+}
44
+
45
+// MSI creates a map[string]interface{} and puts it inside a new Map.
46
+//
47
+// The arguments follow a key, value pattern.
48
+//
49
+// Panics
50
+//
51
+// Panics if any key arugment is non-string or if there are an odd number of arguments.
52
+//
53
+// Example
54
+//
55
+// To easily create Maps:
56
+//
57
+//     m := objx.MSI("name", "Mat", "age", 29, "subobj", objx.MSI("active", true))
58
+//
59
+//     // creates an Map equivalent to
60
+//     m := objx.New(map[string]interface{}{"name": "Mat", "age": 29, "subobj": map[string]interface{}{"active": true}})
61
+func MSI(keyAndValuePairs ...interface{}) Map {
62
+
63
+	newMap := make(map[string]interface{})
64
+	keyAndValuePairsLen := len(keyAndValuePairs)
65
+
66
+	if keyAndValuePairsLen%2 != 0 {
67
+		panic("objx: MSI must have an even number of arguments following the 'key, value' pattern.")
68
+	}
69
+
70
+	for i := 0; i < keyAndValuePairsLen; i = i + 2 {
71
+
72
+		key := keyAndValuePairs[i]
73
+		value := keyAndValuePairs[i+1]
74
+
75
+		// make sure the key is a string
76
+		keyString, keyStringOK := key.(string)
77
+		if !keyStringOK {
78
+			panic("objx: MSI must follow 'string, interface{}' pattern.  " + keyString + " is not a valid key.")
79
+		}
80
+
81
+		newMap[keyString] = value
82
+
83
+	}
84
+
85
+	return New(newMap)
86
+}
87
+
88
+// ****** Conversion Constructors
89
+
90
+// MustFromJSON creates a new Map containing the data specified in the
91
+// jsonString.
92
+//
93
+// Panics if the JSON is invalid.
94
+func MustFromJSON(jsonString string) Map {
95
+	o, err := FromJSON(jsonString)
96
+
97
+	if err != nil {
98
+		panic("objx: MustFromJSON failed with error: " + err.Error())
99
+	}
100
+
101
+	return o
102
+}
103
+
104
+// FromJSON creates a new Map containing the data specified in the
105
+// jsonString.
106
+//
107
+// Returns an error if the JSON is invalid.
108
+func FromJSON(jsonString string) (Map, error) {
109
+
110
+	var data interface{}
111
+	err := json.Unmarshal([]byte(jsonString), &data)
112
+
113
+	if err != nil {
114
+		return Nil, err
115
+	}
116
+
117
+	return New(data), nil
118
+
119
+}
120
+
121
+// FromBase64 creates a new Obj containing the data specified
122
+// in the Base64 string.
123
+//
124
+// The string is an encoded JSON string returned by Base64
125
+func FromBase64(base64String string) (Map, error) {
126
+
127
+	decoder := base64.NewDecoder(base64.StdEncoding, strings.NewReader(base64String))
128
+
129
+	decoded, err := ioutil.ReadAll(decoder)
130
+	if err != nil {
131
+		return nil, err
132
+	}
133
+
134
+	return FromJSON(string(decoded))
135
+}
136
+
137
+// MustFromBase64 creates a new Obj containing the data specified
138
+// in the Base64 string and panics if there is an error.
139
+//
140
+// The string is an encoded JSON string returned by Base64
141
+func MustFromBase64(base64String string) Map {
142
+
143
+	result, err := FromBase64(base64String)
144
+
145
+	if err != nil {
146
+		panic("objx: MustFromBase64 failed with error: " + err.Error())
147
+	}
148
+
149
+	return result
150
+}
151
+
152
+// FromSignedBase64 creates a new Obj containing the data specified
153
+// in the Base64 string.
154
+//
155
+// The string is an encoded JSON string returned by SignedBase64
156
+func FromSignedBase64(base64String, key string) (Map, error) {
157
+	parts := strings.Split(base64String, SignatureSeparator)
158
+	if len(parts) != 2 {
159
+		return nil, errors.New("objx: Signed base64 string is malformed.")
160
+	}
161
+
162
+	sig := HashWithKey(parts[0], key)
163
+	if parts[1] != sig {
164
+		return nil, errors.New("objx: Signature for base64 data does not match.")
165
+	}
166
+
167
+	return FromBase64(parts[0])
168
+}
169
+
170
+// MustFromSignedBase64 creates a new Obj containing the data specified
171
+// in the Base64 string and panics if there is an error.
172
+//
173
+// The string is an encoded JSON string returned by Base64
174
+func MustFromSignedBase64(base64String, key string) Map {
175
+
176
+	result, err := FromSignedBase64(base64String, key)
177
+
178
+	if err != nil {
179
+		panic("objx: MustFromSignedBase64 failed with error: " + err.Error())
180
+	}
181
+
182
+	return result
183
+}
184
+
185
+// FromURLQuery generates a new Obj by parsing the specified
186
+// query.
187
+//
188
+// For queries with multiple values, the first value is selected.
189
+func FromURLQuery(query string) (Map, error) {
190
+
191
+	vals, err := url.ParseQuery(query)
192
+
193
+	if err != nil {
194
+		return nil, err
195
+	}
196
+
197
+	m := make(map[string]interface{})
198
+	for k, vals := range vals {
199
+		m[k] = vals[0]
200
+	}
201
+
202
+	return New(m), nil
203
+}
204
+
205
+// MustFromURLQuery generates a new Obj by parsing the specified
206
+// query.
207
+//
208
+// For queries with multiple values, the first value is selected.
209
+//
210
+// Panics if it encounters an error
211
+func MustFromURLQuery(query string) Map {
212
+
213
+	o, err := FromURLQuery(query)
214
+
215
+	if err != nil {
216
+		panic("objx: MustFromURLQuery failed with error: " + err.Error())
217
+	}
218
+
219
+	return o
220
+
221
+}
0 222
new file mode 100644
... ...
@@ -0,0 +1,81 @@
0
+package objx
1
+
2
+// Exclude returns a new Map with the keys in the specified []string
3
+// excluded.
4
+func (d Map) Exclude(exclude []string) Map {
5
+
6
+	excluded := make(Map)
7
+	for k, v := range d {
8
+		var shouldInclude bool = true
9
+		for _, toExclude := range exclude {
10
+			if k == toExclude {
11
+				shouldInclude = false
12
+				break
13
+			}
14
+		}
15
+		if shouldInclude {
16
+			excluded[k] = v
17
+		}
18
+	}
19
+
20
+	return excluded
21
+}
22
+
23
+// Copy creates a shallow copy of the Obj.
24
+func (m Map) Copy() Map {
25
+	copied := make(map[string]interface{})
26
+	for k, v := range m {
27
+		copied[k] = v
28
+	}
29
+	return New(copied)
30
+}
31
+
32
+// Merge blends the specified map with a copy of this map and returns the result.
33
+//
34
+// Keys that appear in both will be selected from the specified map.
35
+// This method requires that the wrapped object be a map[string]interface{}
36
+func (m Map) Merge(merge Map) Map {
37
+	return m.Copy().MergeHere(merge)
38
+}
39
+
40
+// Merge blends the specified map with this map and returns the current map.
41
+//
42
+// Keys that appear in both will be selected from the specified map.  The original map
43
+// will be modified. This method requires that
44
+// the wrapped object be a map[string]interface{}
45
+func (m Map) MergeHere(merge Map) Map {
46
+
47
+	for k, v := range merge {
48
+		m[k] = v
49
+	}
50
+
51
+	return m
52
+
53
+}
54
+
55
+// Transform builds a new Obj giving the transformer a chance
56
+// to change the keys and values as it goes. This method requires that
57
+// the wrapped object be a map[string]interface{}
58
+func (m Map) Transform(transformer func(key string, value interface{}) (string, interface{})) Map {
59
+	newMap := make(map[string]interface{})
60
+	for k, v := range m {
61
+		modifiedKey, modifiedVal := transformer(k, v)
62
+		newMap[modifiedKey] = modifiedVal
63
+	}
64
+	return New(newMap)
65
+}
66
+
67
+// TransformKeys builds a new map using the specified key mapping.
68
+//
69
+// Unspecified keys will be unaltered.
70
+// This method requires that the wrapped object be a map[string]interface{}
71
+func (m Map) TransformKeys(mapping map[string]string) Map {
72
+	return m.Transform(func(key string, value interface{}) (string, interface{}) {
73
+
74
+		if newKey, ok := mapping[key]; ok {
75
+			return newKey, value
76
+		}
77
+
78
+		return key, value
79
+	})
80
+}
0 81
new file mode 100644
... ...
@@ -0,0 +1,14 @@
0
+package objx
1
+
2
+import (
3
+	"crypto/sha1"
4
+	"encoding/hex"
5
+)
6
+
7
+// HashWithKey hashes the specified string using the security
8
+// key.
9
+func HashWithKey(data, key string) string {
10
+	hash := sha1.New()
11
+	hash.Write([]byte(data + ":" + key))
12
+	return hex.EncodeToString(hash.Sum(nil))
13
+}
0 14
new file mode 100644
... ...
@@ -0,0 +1,17 @@
0
+package objx
1
+
2
+// Has gets whether there is something at the specified selector
3
+// or not.
4
+//
5
+// If m is nil, Has will always return false.
6
+func (m Map) Has(selector string) bool {
7
+	if m == nil {
8
+		return false
9
+	}
10
+	return !m.Get(selector).IsNil()
11
+}
12
+
13
+// IsNil gets whether the data is nil or not.
14
+func (v *Value) IsNil() bool {
15
+	return v == nil || v.data == nil
16
+}
0 17
new file mode 100644
... ...
@@ -0,0 +1,2881 @@
0
+package objx
1
+
2
+/*
3
+	Inter (interface{} and []interface{})
4
+	--------------------------------------------------
5
+*/
6
+
7
+// Inter gets the value as a interface{}, returns the optionalDefault
8
+// value or a system default object if the value is the wrong type.
9
+func (v *Value) Inter(optionalDefault ...interface{}) interface{} {
10
+	if s, ok := v.data.(interface{}); ok {
11
+		return s
12
+	}
13
+	if len(optionalDefault) == 1 {
14
+		return optionalDefault[0]
15
+	}
16
+	return nil
17
+}
18
+
19
+// MustInter gets the value as a interface{}.
20
+//
21
+// Panics if the object is not a interface{}.
22
+func (v *Value) MustInter() interface{} {
23
+	return v.data.(interface{})
24
+}
25
+
26
+// InterSlice gets the value as a []interface{}, returns the optionalDefault
27
+// value or nil if the value is not a []interface{}.
28
+func (v *Value) InterSlice(optionalDefault ...[]interface{}) []interface{} {
29
+	if s, ok := v.data.([]interface{}); ok {
30
+		return s
31
+	}
32
+	if len(optionalDefault) == 1 {
33
+		return optionalDefault[0]
34
+	}
35
+	return nil
36
+}
37
+
38
+// MustInterSlice gets the value as a []interface{}.
39
+//
40
+// Panics if the object is not a []interface{}.
41
+func (v *Value) MustInterSlice() []interface{} {
42
+	return v.data.([]interface{})
43
+}
44
+
45
+// IsInter gets whether the object contained is a interface{} or not.
46
+func (v *Value) IsInter() bool {
47
+	_, ok := v.data.(interface{})
48
+	return ok
49
+}
50
+
51
+// IsInterSlice gets whether the object contained is a []interface{} or not.
52
+func (v *Value) IsInterSlice() bool {
53
+	_, ok := v.data.([]interface{})
54
+	return ok
55
+}
56
+
57
+// EachInter calls the specified callback for each object
58
+// in the []interface{}.
59
+//
60
+// Panics if the object is the wrong type.
61
+func (v *Value) EachInter(callback func(int, interface{}) bool) *Value {
62
+
63
+	for index, val := range v.MustInterSlice() {
64
+		carryon := callback(index, val)
65
+		if carryon == false {
66
+			break
67
+		}
68
+	}
69
+
70
+	return v
71
+
72
+}
73
+
74
+// WhereInter uses the specified decider function to select items
75
+// from the []interface{}.  The object contained in the result will contain
76
+// only the selected items.
77
+func (v *Value) WhereInter(decider func(int, interface{}) bool) *Value {
78
+
79
+	var selected []interface{}
80
+
81
+	v.EachInter(func(index int, val interface{}) bool {
82
+		shouldSelect := decider(index, val)
83
+		if shouldSelect == false {
84
+			selected = append(selected, val)
85
+		}
86
+		return true
87
+	})
88
+
89
+	return &Value{data: selected}
90
+
91
+}
92
+
93
+// GroupInter uses the specified grouper function to group the items
94
+// keyed by the return of the grouper.  The object contained in the
95
+// result will contain a map[string][]interface{}.
96
+func (v *Value) GroupInter(grouper func(int, interface{}) string) *Value {
97
+
98
+	groups := make(map[string][]interface{})
99
+
100
+	v.EachInter(func(index int, val interface{}) bool {
101
+		group := grouper(index, val)
102
+		if _, ok := groups[group]; !ok {
103
+			groups[group] = make([]interface{}, 0)
104
+		}
105
+		groups[group] = append(groups[group], val)
106
+		return true
107
+	})
108
+
109
+	return &Value{data: groups}
110
+
111
+}
112
+
113
+// ReplaceInter uses the specified function to replace each interface{}s
114
+// by iterating each item.  The data in the returned result will be a
115
+// []interface{} containing the replaced items.
116
+func (v *Value) ReplaceInter(replacer func(int, interface{}) interface{}) *Value {
117
+
118
+	arr := v.MustInterSlice()
119
+	replaced := make([]interface{}, len(arr))
120
+
121
+	v.EachInter(func(index int, val interface{}) bool {
122
+		replaced[index] = replacer(index, val)
123
+		return true
124
+	})
125
+
126
+	return &Value{data: replaced}
127
+
128
+}
129
+
130
+// CollectInter uses the specified collector function to collect a value
131
+// for each of the interface{}s in the slice.  The data returned will be a
132
+// []interface{}.
133
+func (v *Value) CollectInter(collector func(int, interface{}) interface{}) *Value {
134
+
135
+	arr := v.MustInterSlice()
136
+	collected := make([]interface{}, len(arr))
137
+
138
+	v.EachInter(func(index int, val interface{}) bool {
139
+		collected[index] = collector(index, val)
140
+		return true
141
+	})
142
+
143
+	return &Value{data: collected}
144
+}
145
+
146
+/*
147
+	MSI (map[string]interface{} and []map[string]interface{})
148
+	--------------------------------------------------
149
+*/
150
+
151
+// MSI gets the value as a map[string]interface{}, returns the optionalDefault
152
+// value or a system default object if the value is the wrong type.
153
+func (v *Value) MSI(optionalDefault ...map[string]interface{}) map[string]interface{} {
154
+	if s, ok := v.data.(map[string]interface{}); ok {
155
+		return s
156
+	}
157
+	if len(optionalDefault) == 1 {
158
+		return optionalDefault[0]
159
+	}
160
+	return nil
161
+}
162
+
163
+// MustMSI gets the value as a map[string]interface{}.
164
+//
165
+// Panics if the object is not a map[string]interface{}.
166
+func (v *Value) MustMSI() map[string]interface{} {
167
+	return v.data.(map[string]interface{})
168
+}
169
+
170
+// MSISlice gets the value as a []map[string]interface{}, returns the optionalDefault
171
+// value or nil if the value is not a []map[string]interface{}.
172
+func (v *Value) MSISlice(optionalDefault ...[]map[string]interface{}) []map[string]interface{} {
173
+	if s, ok := v.data.([]map[string]interface{}); ok {
174
+		return s
175
+	}
176
+	if len(optionalDefault) == 1 {
177
+		return optionalDefault[0]
178
+	}
179
+	return nil
180
+}
181
+
182
+// MustMSISlice gets the value as a []map[string]interface{}.
183
+//
184
+// Panics if the object is not a []map[string]interface{}.
185
+func (v *Value) MustMSISlice() []map[string]interface{} {
186
+	return v.data.([]map[string]interface{})
187
+}
188
+
189
+// IsMSI gets whether the object contained is a map[string]interface{} or not.
190
+func (v *Value) IsMSI() bool {
191
+	_, ok := v.data.(map[string]interface{})
192
+	return ok
193
+}
194
+
195
+// IsMSISlice gets whether the object contained is a []map[string]interface{} or not.
196
+func (v *Value) IsMSISlice() bool {
197
+	_, ok := v.data.([]map[string]interface{})
198
+	return ok
199
+}
200
+
201
+// EachMSI calls the specified callback for each object
202
+// in the []map[string]interface{}.
203
+//
204
+// Panics if the object is the wrong type.
205
+func (v *Value) EachMSI(callback func(int, map[string]interface{}) bool) *Value {
206
+
207
+	for index, val := range v.MustMSISlice() {
208
+		carryon := callback(index, val)
209
+		if carryon == false {
210
+			break
211
+		}
212
+	}
213
+
214
+	return v
215
+
216
+}
217
+
218
+// WhereMSI uses the specified decider function to select items
219
+// from the []map[string]interface{}.  The object contained in the result will contain
220
+// only the selected items.
221
+func (v *Value) WhereMSI(decider func(int, map[string]interface{}) bool) *Value {
222
+
223
+	var selected []map[string]interface{}
224
+
225
+	v.EachMSI(func(index int, val map[string]interface{}) bool {
226
+		shouldSelect := decider(index, val)
227
+		if shouldSelect == false {
228
+			selected = append(selected, val)
229
+		}
230
+		return true
231
+	})
232
+
233
+	return &Value{data: selected}
234
+
235
+}
236
+
237
+// GroupMSI uses the specified grouper function to group the items
238
+// keyed by the return of the grouper.  The object contained in the
239
+// result will contain a map[string][]map[string]interface{}.
240
+func (v *Value) GroupMSI(grouper func(int, map[string]interface{}) string) *Value {
241
+
242
+	groups := make(map[string][]map[string]interface{})
243
+
244
+	v.EachMSI(func(index int, val map[string]interface{}) bool {
245
+		group := grouper(index, val)
246
+		if _, ok := groups[group]; !ok {
247
+			groups[group] = make([]map[string]interface{}, 0)
248
+		}
249
+		groups[group] = append(groups[group], val)
250
+		return true
251
+	})
252
+
253
+	return &Value{data: groups}
254
+
255
+}
256
+
257
+// ReplaceMSI uses the specified function to replace each map[string]interface{}s
258
+// by iterating each item.  The data in the returned result will be a
259
+// []map[string]interface{} containing the replaced items.
260
+func (v *Value) ReplaceMSI(replacer func(int, map[string]interface{}) map[string]interface{}) *Value {
261
+
262
+	arr := v.MustMSISlice()
263
+	replaced := make([]map[string]interface{}, len(arr))
264
+
265
+	v.EachMSI(func(index int, val map[string]interface{}) bool {
266
+		replaced[index] = replacer(index, val)
267
+		return true
268
+	})
269
+
270
+	return &Value{data: replaced}
271
+
272
+}
273
+
274
+// CollectMSI uses the specified collector function to collect a value
275
+// for each of the map[string]interface{}s in the slice.  The data returned will be a
276
+// []interface{}.
277
+func (v *Value) CollectMSI(collector func(int, map[string]interface{}) interface{}) *Value {
278
+
279
+	arr := v.MustMSISlice()
280
+	collected := make([]interface{}, len(arr))
281
+
282
+	v.EachMSI(func(index int, val map[string]interface{}) bool {
283
+		collected[index] = collector(index, val)
284
+		return true
285
+	})
286
+
287
+	return &Value{data: collected}
288
+}
289
+
290
+/*
291
+	ObjxMap ((Map) and [](Map))
292
+	--------------------------------------------------
293
+*/
294
+
295
+// ObjxMap gets the value as a (Map), returns the optionalDefault
296
+// value or a system default object if the value is the wrong type.
297
+func (v *Value) ObjxMap(optionalDefault ...(Map)) Map {
298
+	if s, ok := v.data.((Map)); ok {
299
+		return s
300
+	}
301
+	if len(optionalDefault) == 1 {
302
+		return optionalDefault[0]
303
+	}
304
+	return New(nil)
305
+}
306
+
307
+// MustObjxMap gets the value as a (Map).
308
+//
309
+// Panics if the object is not a (Map).
310
+func (v *Value) MustObjxMap() Map {
311
+	return v.data.((Map))
312
+}
313
+
314
+// ObjxMapSlice gets the value as a [](Map), returns the optionalDefault
315
+// value or nil if the value is not a [](Map).
316
+func (v *Value) ObjxMapSlice(optionalDefault ...[](Map)) [](Map) {
317
+	if s, ok := v.data.([](Map)); ok {
318
+		return s
319
+	}
320
+	if len(optionalDefault) == 1 {
321
+		return optionalDefault[0]
322
+	}
323
+	return nil
324
+}
325
+
326
+// MustObjxMapSlice gets the value as a [](Map).
327
+//
328
+// Panics if the object is not a [](Map).
329
+func (v *Value) MustObjxMapSlice() [](Map) {
330
+	return v.data.([](Map))
331
+}
332
+
333
+// IsObjxMap gets whether the object contained is a (Map) or not.
334
+func (v *Value) IsObjxMap() bool {
335
+	_, ok := v.data.((Map))
336
+	return ok
337
+}
338
+
339
+// IsObjxMapSlice gets whether the object contained is a [](Map) or not.
340
+func (v *Value) IsObjxMapSlice() bool {
341
+	_, ok := v.data.([](Map))
342
+	return ok
343
+}
344
+
345
+// EachObjxMap calls the specified callback for each object
346
+// in the [](Map).
347
+//
348
+// Panics if the object is the wrong type.
349
+func (v *Value) EachObjxMap(callback func(int, Map) bool) *Value {
350
+
351
+	for index, val := range v.MustObjxMapSlice() {
352
+		carryon := callback(index, val)
353
+		if carryon == false {
354
+			break
355
+		}
356
+	}
357
+
358
+	return v
359
+
360
+}
361
+
362
+// WhereObjxMap uses the specified decider function to select items
363
+// from the [](Map).  The object contained in the result will contain
364
+// only the selected items.
365
+func (v *Value) WhereObjxMap(decider func(int, Map) bool) *Value {
366
+
367
+	var selected [](Map)
368
+
369
+	v.EachObjxMap(func(index int, val Map) bool {
370
+		shouldSelect := decider(index, val)
371
+		if shouldSelect == false {
372
+			selected = append(selected, val)
373
+		}
374
+		return true
375
+	})
376
+
377
+	return &Value{data: selected}
378
+
379
+}
380
+
381
+// GroupObjxMap uses the specified grouper function to group the items
382
+// keyed by the return of the grouper.  The object contained in the
383
+// result will contain a map[string][](Map).
384
+func (v *Value) GroupObjxMap(grouper func(int, Map) string) *Value {
385
+
386
+	groups := make(map[string][](Map))
387
+
388
+	v.EachObjxMap(func(index int, val Map) bool {
389
+		group := grouper(index, val)
390
+		if _, ok := groups[group]; !ok {
391
+			groups[group] = make([](Map), 0)
392
+		}
393
+		groups[group] = append(groups[group], val)
394
+		return true
395
+	})
396
+
397
+	return &Value{data: groups}
398
+
399
+}
400
+
401
+// ReplaceObjxMap uses the specified function to replace each (Map)s
402
+// by iterating each item.  The data in the returned result will be a
403
+// [](Map) containing the replaced items.
404
+func (v *Value) ReplaceObjxMap(replacer func(int, Map) Map) *Value {
405
+
406
+	arr := v.MustObjxMapSlice()
407
+	replaced := make([](Map), len(arr))
408
+
409
+	v.EachObjxMap(func(index int, val Map) bool {
410
+		replaced[index] = replacer(index, val)
411
+		return true
412
+	})
413
+
414
+	return &Value{data: replaced}
415
+
416
+}
417
+
418
+// CollectObjxMap uses the specified collector function to collect a value
419
+// for each of the (Map)s in the slice.  The data returned will be a
420
+// []interface{}.
421
+func (v *Value) CollectObjxMap(collector func(int, Map) interface{}) *Value {
422
+
423
+	arr := v.MustObjxMapSlice()
424
+	collected := make([]interface{}, len(arr))
425
+
426
+	v.EachObjxMap(func(index int, val Map) bool {
427
+		collected[index] = collector(index, val)
428
+		return true
429
+	})
430
+
431
+	return &Value{data: collected}
432
+}
433
+
434
+/*
435
+	Bool (bool and []bool)
436
+	--------------------------------------------------
437
+*/
438
+
439
+// Bool gets the value as a bool, returns the optionalDefault
440
+// value or a system default object if the value is the wrong type.
441
+func (v *Value) Bool(optionalDefault ...bool) bool {
442
+	if s, ok := v.data.(bool); ok {
443
+		return s
444
+	}
445
+	if len(optionalDefault) == 1 {
446
+		return optionalDefault[0]
447
+	}
448
+	return false
449
+}
450
+
451
+// MustBool gets the value as a bool.
452
+//
453
+// Panics if the object is not a bool.
454
+func (v *Value) MustBool() bool {
455
+	return v.data.(bool)
456
+}
457
+
458
+// BoolSlice gets the value as a []bool, returns the optionalDefault
459
+// value or nil if the value is not a []bool.
460
+func (v *Value) BoolSlice(optionalDefault ...[]bool) []bool {
461
+	if s, ok := v.data.([]bool); ok {
462
+		return s
463
+	}
464
+	if len(optionalDefault) == 1 {
465
+		return optionalDefault[0]
466
+	}
467
+	return nil
468
+}
469
+
470
+// MustBoolSlice gets the value as a []bool.
471
+//
472
+// Panics if the object is not a []bool.
473
+func (v *Value) MustBoolSlice() []bool {
474
+	return v.data.([]bool)
475
+}
476
+
477
+// IsBool gets whether the object contained is a bool or not.
478
+func (v *Value) IsBool() bool {
479
+	_, ok := v.data.(bool)
480
+	return ok
481
+}
482
+
483
+// IsBoolSlice gets whether the object contained is a []bool or not.
484
+func (v *Value) IsBoolSlice() bool {
485
+	_, ok := v.data.([]bool)
486
+	return ok
487
+}
488
+
489
+// EachBool calls the specified callback for each object
490
+// in the []bool.
491
+//
492
+// Panics if the object is the wrong type.
493
+func (v *Value) EachBool(callback func(int, bool) bool) *Value {
494
+
495
+	for index, val := range v.MustBoolSlice() {
496
+		carryon := callback(index, val)
497
+		if carryon == false {
498
+			break
499
+		}
500
+	}
501
+
502
+	return v
503
+
504
+}
505
+
506
+// WhereBool uses the specified decider function to select items
507
+// from the []bool.  The object contained in the result will contain
508
+// only the selected items.
509
+func (v *Value) WhereBool(decider func(int, bool) bool) *Value {
510
+
511
+	var selected []bool
512
+
513
+	v.EachBool(func(index int, val bool) bool {
514
+		shouldSelect := decider(index, val)
515
+		if shouldSelect == false {
516
+			selected = append(selected, val)
517
+		}
518
+		return true
519
+	})
520
+
521
+	return &Value{data: selected}
522
+
523
+}
524
+
525
+// GroupBool uses the specified grouper function to group the items
526
+// keyed by the return of the grouper.  The object contained in the
527
+// result will contain a map[string][]bool.
528
+func (v *Value) GroupBool(grouper func(int, bool) string) *Value {
529
+
530
+	groups := make(map[string][]bool)
531
+
532
+	v.EachBool(func(index int, val bool) bool {
533
+		group := grouper(index, val)
534
+		if _, ok := groups[group]; !ok {
535
+			groups[group] = make([]bool, 0)
536
+		}
537
+		groups[group] = append(groups[group], val)
538
+		return true
539
+	})
540
+
541
+	return &Value{data: groups}
542
+
543
+}
544
+
545
+// ReplaceBool uses the specified function to replace each bools
546
+// by iterating each item.  The data in the returned result will be a
547
+// []bool containing the replaced items.
548
+func (v *Value) ReplaceBool(replacer func(int, bool) bool) *Value {
549
+
550
+	arr := v.MustBoolSlice()
551
+	replaced := make([]bool, len(arr))
552
+
553
+	v.EachBool(func(index int, val bool) bool {
554
+		replaced[index] = replacer(index, val)
555
+		return true
556
+	})
557
+
558
+	return &Value{data: replaced}
559
+
560
+}
561
+
562
+// CollectBool uses the specified collector function to collect a value
563
+// for each of the bools in the slice.  The data returned will be a
564
+// []interface{}.
565
+func (v *Value) CollectBool(collector func(int, bool) interface{}) *Value {
566
+
567
+	arr := v.MustBoolSlice()
568
+	collected := make([]interface{}, len(arr))
569
+
570
+	v.EachBool(func(index int, val bool) bool {
571
+		collected[index] = collector(index, val)
572
+		return true
573
+	})
574
+
575
+	return &Value{data: collected}
576
+}
577
+
578
+/*
579
+	Str (string and []string)
580
+	--------------------------------------------------
581
+*/
582
+
583
+// Str gets the value as a string, returns the optionalDefault
584
+// value or a system default object if the value is the wrong type.
585
+func (v *Value) Str(optionalDefault ...string) string {
586
+	if s, ok := v.data.(string); ok {
587
+		return s
588
+	}
589
+	if len(optionalDefault) == 1 {
590
+		return optionalDefault[0]
591
+	}
592
+	return ""
593
+}
594
+
595
+// MustStr gets the value as a string.
596
+//
597
+// Panics if the object is not a string.
598
+func (v *Value) MustStr() string {
599
+	return v.data.(string)
600
+}
601
+
602
+// StrSlice gets the value as a []string, returns the optionalDefault
603
+// value or nil if the value is not a []string.
604
+func (v *Value) StrSlice(optionalDefault ...[]string) []string {
605
+	if s, ok := v.data.([]string); ok {
606
+		return s
607
+	}
608
+	if len(optionalDefault) == 1 {
609
+		return optionalDefault[0]
610
+	}
611
+	return nil
612
+}
613
+
614
+// MustStrSlice gets the value as a []string.
615
+//
616
+// Panics if the object is not a []string.
617
+func (v *Value) MustStrSlice() []string {
618
+	return v.data.([]string)
619
+}
620
+
621
+// IsStr gets whether the object contained is a string or not.
622
+func (v *Value) IsStr() bool {
623
+	_, ok := v.data.(string)
624
+	return ok
625
+}
626
+
627
+// IsStrSlice gets whether the object contained is a []string or not.
628
+func (v *Value) IsStrSlice() bool {
629
+	_, ok := v.data.([]string)
630
+	return ok
631
+}
632
+
633
+// EachStr calls the specified callback for each object
634
+// in the []string.
635
+//
636
+// Panics if the object is the wrong type.
637
+func (v *Value) EachStr(callback func(int, string) bool) *Value {
638
+
639
+	for index, val := range v.MustStrSlice() {
640
+		carryon := callback(index, val)
641
+		if carryon == false {
642
+			break
643
+		}
644
+	}
645
+
646
+	return v
647
+
648
+}
649
+
650
+// WhereStr uses the specified decider function to select items
651
+// from the []string.  The object contained in the result will contain
652
+// only the selected items.
653
+func (v *Value) WhereStr(decider func(int, string) bool) *Value {
654
+
655
+	var selected []string
656
+
657
+	v.EachStr(func(index int, val string) bool {
658
+		shouldSelect := decider(index, val)
659
+		if shouldSelect == false {
660
+			selected = append(selected, val)
661
+		}
662
+		return true
663
+	})
664
+
665
+	return &Value{data: selected}
666
+
667
+}
668
+
669
+// GroupStr uses the specified grouper function to group the items
670
+// keyed by the return of the grouper.  The object contained in the
671
+// result will contain a map[string][]string.
672
+func (v *Value) GroupStr(grouper func(int, string) string) *Value {
673
+
674
+	groups := make(map[string][]string)
675
+
676
+	v.EachStr(func(index int, val string) bool {
677
+		group := grouper(index, val)
678
+		if _, ok := groups[group]; !ok {
679
+			groups[group] = make([]string, 0)
680
+		}
681
+		groups[group] = append(groups[group], val)
682
+		return true
683
+	})
684
+
685
+	return &Value{data: groups}
686
+
687
+}
688
+
689
+// ReplaceStr uses the specified function to replace each strings
690
+// by iterating each item.  The data in the returned result will be a
691
+// []string containing the replaced items.
692
+func (v *Value) ReplaceStr(replacer func(int, string) string) *Value {
693
+
694
+	arr := v.MustStrSlice()
695
+	replaced := make([]string, len(arr))
696
+
697
+	v.EachStr(func(index int, val string) bool {
698
+		replaced[index] = replacer(index, val)
699
+		return true
700
+	})
701
+
702
+	return &Value{data: replaced}
703
+
704
+}
705
+
706
+// CollectStr uses the specified collector function to collect a value
707
+// for each of the strings in the slice.  The data returned will be a
708
+// []interface{}.
709
+func (v *Value) CollectStr(collector func(int, string) interface{}) *Value {
710
+
711
+	arr := v.MustStrSlice()
712
+	collected := make([]interface{}, len(arr))
713
+
714
+	v.EachStr(func(index int, val string) bool {
715
+		collected[index] = collector(index, val)
716
+		return true
717
+	})
718
+
719
+	return &Value{data: collected}
720
+}
721
+
722
+/*
723
+	Int (int and []int)
724
+	--------------------------------------------------
725
+*/
726
+
727
+// Int gets the value as a int, returns the optionalDefault
728
+// value or a system default object if the value is the wrong type.
729
+func (v *Value) Int(optionalDefault ...int) int {
730
+	if s, ok := v.data.(int); ok {
731
+		return s
732
+	}
733
+	if len(optionalDefault) == 1 {
734
+		return optionalDefault[0]
735
+	}
736
+	return 0
737
+}
738
+
739
+// MustInt gets the value as a int.
740
+//
741
+// Panics if the object is not a int.
742
+func (v *Value) MustInt() int {
743
+	return v.data.(int)
744
+}
745
+
746
+// IntSlice gets the value as a []int, returns the optionalDefault
747
+// value or nil if the value is not a []int.
748
+func (v *Value) IntSlice(optionalDefault ...[]int) []int {
749
+	if s, ok := v.data.([]int); ok {
750
+		return s
751
+	}
752
+	if len(optionalDefault) == 1 {
753
+		return optionalDefault[0]
754
+	}
755
+	return nil
756
+}
757
+
758
+// MustIntSlice gets the value as a []int.
759
+//
760
+// Panics if the object is not a []int.
761
+func (v *Value) MustIntSlice() []int {
762
+	return v.data.([]int)
763
+}
764
+
765
+// IsInt gets whether the object contained is a int or not.
766
+func (v *Value) IsInt() bool {
767
+	_, ok := v.data.(int)
768
+	return ok
769
+}
770
+
771
+// IsIntSlice gets whether the object contained is a []int or not.
772
+func (v *Value) IsIntSlice() bool {
773
+	_, ok := v.data.([]int)
774
+	return ok
775
+}
776
+
777
+// EachInt calls the specified callback for each object
778
+// in the []int.
779
+//
780
+// Panics if the object is the wrong type.
781
+func (v *Value) EachInt(callback func(int, int) bool) *Value {
782
+
783
+	for index, val := range v.MustIntSlice() {
784
+		carryon := callback(index, val)
785
+		if carryon == false {
786
+			break
787
+		}
788
+	}
789
+
790
+	return v
791
+
792
+}
793
+
794
+// WhereInt uses the specified decider function to select items
795
+// from the []int.  The object contained in the result will contain
796
+// only the selected items.
797
+func (v *Value) WhereInt(decider func(int, int) bool) *Value {
798
+
799
+	var selected []int
800
+
801
+	v.EachInt(func(index int, val int) bool {
802
+		shouldSelect := decider(index, val)
803
+		if shouldSelect == false {
804
+			selected = append(selected, val)
805
+		}
806
+		return true
807
+	})
808
+
809
+	return &Value{data: selected}
810
+
811
+}
812
+
813
+// GroupInt uses the specified grouper function to group the items
814
+// keyed by the return of the grouper.  The object contained in the
815
+// result will contain a map[string][]int.
816
+func (v *Value) GroupInt(grouper func(int, int) string) *Value {
817
+
818
+	groups := make(map[string][]int)
819
+
820
+	v.EachInt(func(index int, val int) bool {
821
+		group := grouper(index, val)
822
+		if _, ok := groups[group]; !ok {
823
+			groups[group] = make([]int, 0)
824
+		}
825
+		groups[group] = append(groups[group], val)
826
+		return true
827
+	})
828
+
829
+	return &Value{data: groups}
830
+
831
+}
832
+
833
+// ReplaceInt uses the specified function to replace each ints
834
+// by iterating each item.  The data in the returned result will be a
835
+// []int containing the replaced items.
836
+func (v *Value) ReplaceInt(replacer func(int, int) int) *Value {
837
+
838
+	arr := v.MustIntSlice()
839
+	replaced := make([]int, len(arr))
840
+
841
+	v.EachInt(func(index int, val int) bool {
842
+		replaced[index] = replacer(index, val)
843
+		return true
844
+	})
845
+
846
+	return &Value{data: replaced}
847
+
848
+}
849
+
850
+// CollectInt uses the specified collector function to collect a value
851
+// for each of the ints in the slice.  The data returned will be a
852
+// []interface{}.
853
+func (v *Value) CollectInt(collector func(int, int) interface{}) *Value {
854
+
855
+	arr := v.MustIntSlice()
856
+	collected := make([]interface{}, len(arr))
857
+
858
+	v.EachInt(func(index int, val int) bool {
859
+		collected[index] = collector(index, val)
860
+		return true
861
+	})
862
+
863
+	return &Value{data: collected}
864
+}
865
+
866
+/*
867
+	Int8 (int8 and []int8)
868
+	--------------------------------------------------
869
+*/
870
+
871
+// Int8 gets the value as a int8, returns the optionalDefault
872
+// value or a system default object if the value is the wrong type.
873
+func (v *Value) Int8(optionalDefault ...int8) int8 {
874
+	if s, ok := v.data.(int8); ok {
875
+		return s
876
+	}
877
+	if len(optionalDefault) == 1 {
878
+		return optionalDefault[0]
879
+	}
880
+	return 0
881
+}
882
+
883
+// MustInt8 gets the value as a int8.
884
+//
885
+// Panics if the object is not a int8.
886
+func (v *Value) MustInt8() int8 {
887
+	return v.data.(int8)
888
+}
889
+
890
+// Int8Slice gets the value as a []int8, returns the optionalDefault
891
+// value or nil if the value is not a []int8.
892
+func (v *Value) Int8Slice(optionalDefault ...[]int8) []int8 {
893
+	if s, ok := v.data.([]int8); ok {
894
+		return s
895
+	}
896
+	if len(optionalDefault) == 1 {
897
+		return optionalDefault[0]
898
+	}
899
+	return nil
900
+}
901
+
902
+// MustInt8Slice gets the value as a []int8.
903
+//
904
+// Panics if the object is not a []int8.
905
+func (v *Value) MustInt8Slice() []int8 {
906
+	return v.data.([]int8)
907
+}
908
+
909
+// IsInt8 gets whether the object contained is a int8 or not.
910
+func (v *Value) IsInt8() bool {
911
+	_, ok := v.data.(int8)
912
+	return ok
913
+}
914
+
915
+// IsInt8Slice gets whether the object contained is a []int8 or not.
916
+func (v *Value) IsInt8Slice() bool {
917
+	_, ok := v.data.([]int8)
918
+	return ok
919
+}
920
+
921
+// EachInt8 calls the specified callback for each object
922
+// in the []int8.
923
+//
924
+// Panics if the object is the wrong type.
925
+func (v *Value) EachInt8(callback func(int, int8) bool) *Value {
926
+
927
+	for index, val := range v.MustInt8Slice() {
928
+		carryon := callback(index, val)
929
+		if carryon == false {
930
+			break
931
+		}
932
+	}
933
+
934
+	return v
935
+
936
+}
937
+
938
+// WhereInt8 uses the specified decider function to select items
939
+// from the []int8.  The object contained in the result will contain
940
+// only the selected items.
941
+func (v *Value) WhereInt8(decider func(int, int8) bool) *Value {
942
+
943
+	var selected []int8
944
+
945
+	v.EachInt8(func(index int, val int8) bool {
946
+		shouldSelect := decider(index, val)
947
+		if shouldSelect == false {
948
+			selected = append(selected, val)
949
+		}
950
+		return true
951
+	})
952
+
953
+	return &Value{data: selected}
954
+
955
+}
956
+
957
+// GroupInt8 uses the specified grouper function to group the items
958
+// keyed by the return of the grouper.  The object contained in the
959
+// result will contain a map[string][]int8.
960
+func (v *Value) GroupInt8(grouper func(int, int8) string) *Value {
961
+
962
+	groups := make(map[string][]int8)
963
+
964
+	v.EachInt8(func(index int, val int8) bool {
965
+		group := grouper(index, val)
966
+		if _, ok := groups[group]; !ok {
967
+			groups[group] = make([]int8, 0)
968
+		}
969
+		groups[group] = append(groups[group], val)
970
+		return true
971
+	})
972
+
973
+	return &Value{data: groups}
974
+
975
+}
976
+
977
+// ReplaceInt8 uses the specified function to replace each int8s
978
+// by iterating each item.  The data in the returned result will be a
979
+// []int8 containing the replaced items.
980
+func (v *Value) ReplaceInt8(replacer func(int, int8) int8) *Value {
981
+
982
+	arr := v.MustInt8Slice()
983
+	replaced := make([]int8, len(arr))
984
+
985
+	v.EachInt8(func(index int, val int8) bool {
986
+		replaced[index] = replacer(index, val)
987
+		return true
988
+	})
989
+
990
+	return &Value{data: replaced}
991
+
992
+}
993
+
994
+// CollectInt8 uses the specified collector function to collect a value
995
+// for each of the int8s in the slice.  The data returned will be a
996
+// []interface{}.
997
+func (v *Value) CollectInt8(collector func(int, int8) interface{}) *Value {
998
+
999
+	arr := v.MustInt8Slice()
1000
+	collected := make([]interface{}, len(arr))
1001
+
1002
+	v.EachInt8(func(index int, val int8) bool {
1003
+		collected[index] = collector(index, val)
1004
+		return true
1005
+	})
1006
+
1007
+	return &Value{data: collected}
1008
+}
1009
+
1010
+/*
1011
+	Int16 (int16 and []int16)
1012
+	--------------------------------------------------
1013
+*/
1014
+
1015
+// Int16 gets the value as a int16, returns the optionalDefault
1016
+// value or a system default object if the value is the wrong type.
1017
+func (v *Value) Int16(optionalDefault ...int16) int16 {
1018
+	if s, ok := v.data.(int16); ok {
1019
+		return s
1020
+	}
1021
+	if len(optionalDefault) == 1 {
1022
+		return optionalDefault[0]
1023
+	}
1024
+	return 0
1025
+}
1026
+
1027
+// MustInt16 gets the value as a int16.
1028
+//
1029
+// Panics if the object is not a int16.
1030
+func (v *Value) MustInt16() int16 {
1031
+	return v.data.(int16)
1032
+}
1033
+
1034
+// Int16Slice gets the value as a []int16, returns the optionalDefault
1035
+// value or nil if the value is not a []int16.
1036
+func (v *Value) Int16Slice(optionalDefault ...[]int16) []int16 {
1037
+	if s, ok := v.data.([]int16); ok {
1038
+		return s
1039
+	}
1040
+	if len(optionalDefault) == 1 {
1041
+		return optionalDefault[0]
1042
+	}
1043
+	return nil
1044
+}
1045
+
1046
+// MustInt16Slice gets the value as a []int16.
1047
+//
1048
+// Panics if the object is not a []int16.
1049
+func (v *Value) MustInt16Slice() []int16 {
1050
+	return v.data.([]int16)
1051
+}
1052
+
1053
+// IsInt16 gets whether the object contained is a int16 or not.
1054
+func (v *Value) IsInt16() bool {
1055
+	_, ok := v.data.(int16)
1056
+	return ok
1057
+}
1058
+
1059
+// IsInt16Slice gets whether the object contained is a []int16 or not.
1060
+func (v *Value) IsInt16Slice() bool {
1061
+	_, ok := v.data.([]int16)
1062
+	return ok
1063
+}
1064
+
1065
+// EachInt16 calls the specified callback for each object
1066
+// in the []int16.
1067
+//
1068
+// Panics if the object is the wrong type.
1069
+func (v *Value) EachInt16(callback func(int, int16) bool) *Value {
1070
+
1071
+	for index, val := range v.MustInt16Slice() {
1072
+		carryon := callback(index, val)
1073
+		if carryon == false {
1074
+			break
1075
+		}
1076
+	}
1077
+
1078
+	return v
1079
+
1080
+}
1081
+
1082
+// WhereInt16 uses the specified decider function to select items
1083
+// from the []int16.  The object contained in the result will contain
1084
+// only the selected items.
1085
+func (v *Value) WhereInt16(decider func(int, int16) bool) *Value {
1086
+
1087
+	var selected []int16
1088
+
1089
+	v.EachInt16(func(index int, val int16) bool {
1090
+		shouldSelect := decider(index, val)
1091
+		if shouldSelect == false {
1092
+			selected = append(selected, val)
1093
+		}
1094
+		return true
1095
+	})
1096
+
1097
+	return &Value{data: selected}
1098
+
1099
+}
1100
+
1101
+// GroupInt16 uses the specified grouper function to group the items
1102
+// keyed by the return of the grouper.  The object contained in the
1103
+// result will contain a map[string][]int16.
1104
+func (v *Value) GroupInt16(grouper func(int, int16) string) *Value {
1105
+
1106
+	groups := make(map[string][]int16)
1107
+
1108
+	v.EachInt16(func(index int, val int16) bool {
1109
+		group := grouper(index, val)
1110
+		if _, ok := groups[group]; !ok {
1111
+			groups[group] = make([]int16, 0)
1112
+		}
1113
+		groups[group] = append(groups[group], val)
1114
+		return true
1115
+	})
1116
+
1117
+	return &Value{data: groups}
1118
+
1119
+}
1120
+
1121
+// ReplaceInt16 uses the specified function to replace each int16s
1122
+// by iterating each item.  The data in the returned result will be a
1123
+// []int16 containing the replaced items.
1124
+func (v *Value) ReplaceInt16(replacer func(int, int16) int16) *Value {
1125
+
1126
+	arr := v.MustInt16Slice()
1127
+	replaced := make([]int16, len(arr))
1128
+
1129
+	v.EachInt16(func(index int, val int16) bool {
1130
+		replaced[index] = replacer(index, val)
1131
+		return true
1132
+	})
1133
+
1134
+	return &Value{data: replaced}
1135
+
1136
+}
1137
+
1138
+// CollectInt16 uses the specified collector function to collect a value
1139
+// for each of the int16s in the slice.  The data returned will be a
1140
+// []interface{}.
1141
+func (v *Value) CollectInt16(collector func(int, int16) interface{}) *Value {
1142
+
1143
+	arr := v.MustInt16Slice()
1144
+	collected := make([]interface{}, len(arr))
1145
+
1146
+	v.EachInt16(func(index int, val int16) bool {
1147
+		collected[index] = collector(index, val)
1148
+		return true
1149
+	})
1150
+
1151
+	return &Value{data: collected}
1152
+}
1153
+
1154
+/*
1155
+	Int32 (int32 and []int32)
1156
+	--------------------------------------------------
1157
+*/
1158
+
1159
+// Int32 gets the value as a int32, returns the optionalDefault
1160
+// value or a system default object if the value is the wrong type.
1161
+func (v *Value) Int32(optionalDefault ...int32) int32 {
1162
+	if s, ok := v.data.(int32); ok {
1163
+		return s
1164
+	}
1165
+	if len(optionalDefault) == 1 {
1166
+		return optionalDefault[0]
1167
+	}
1168
+	return 0
1169
+}
1170
+
1171
+// MustInt32 gets the value as a int32.
1172
+//
1173
+// Panics if the object is not a int32.
1174
+func (v *Value) MustInt32() int32 {
1175
+	return v.data.(int32)
1176
+}
1177
+
1178
+// Int32Slice gets the value as a []int32, returns the optionalDefault
1179
+// value or nil if the value is not a []int32.
1180
+func (v *Value) Int32Slice(optionalDefault ...[]int32) []int32 {
1181
+	if s, ok := v.data.([]int32); ok {
1182
+		return s
1183
+	}
1184
+	if len(optionalDefault) == 1 {
1185
+		return optionalDefault[0]
1186
+	}
1187
+	return nil
1188
+}
1189
+
1190
+// MustInt32Slice gets the value as a []int32.
1191
+//
1192
+// Panics if the object is not a []int32.
1193
+func (v *Value) MustInt32Slice() []int32 {
1194
+	return v.data.([]int32)
1195
+}
1196
+
1197
+// IsInt32 gets whether the object contained is a int32 or not.
1198
+func (v *Value) IsInt32() bool {
1199
+	_, ok := v.data.(int32)
1200
+	return ok
1201
+}
1202
+
1203
+// IsInt32Slice gets whether the object contained is a []int32 or not.
1204
+func (v *Value) IsInt32Slice() bool {
1205
+	_, ok := v.data.([]int32)
1206
+	return ok
1207
+}
1208
+
1209
+// EachInt32 calls the specified callback for each object
1210
+// in the []int32.
1211
+//
1212
+// Panics if the object is the wrong type.
1213
+func (v *Value) EachInt32(callback func(int, int32) bool) *Value {
1214
+
1215
+	for index, val := range v.MustInt32Slice() {
1216
+		carryon := callback(index, val)
1217
+		if carryon == false {
1218
+			break
1219
+		}
1220
+	}
1221
+
1222
+	return v
1223
+
1224
+}
1225
+
1226
+// WhereInt32 uses the specified decider function to select items
1227
+// from the []int32.  The object contained in the result will contain
1228
+// only the selected items.
1229
+func (v *Value) WhereInt32(decider func(int, int32) bool) *Value {
1230
+
1231
+	var selected []int32
1232
+
1233
+	v.EachInt32(func(index int, val int32) bool {
1234
+		shouldSelect := decider(index, val)
1235
+		if shouldSelect == false {
1236
+			selected = append(selected, val)
1237
+		}
1238
+		return true
1239
+	})
1240
+
1241
+	return &Value{data: selected}
1242
+
1243
+}
1244
+
1245
+// GroupInt32 uses the specified grouper function to group the items
1246
+// keyed by the return of the grouper.  The object contained in the
1247
+// result will contain a map[string][]int32.
1248
+func (v *Value) GroupInt32(grouper func(int, int32) string) *Value {
1249
+
1250
+	groups := make(map[string][]int32)
1251
+
1252
+	v.EachInt32(func(index int, val int32) bool {
1253
+		group := grouper(index, val)
1254
+		if _, ok := groups[group]; !ok {
1255
+			groups[group] = make([]int32, 0)
1256
+		}
1257
+		groups[group] = append(groups[group], val)
1258
+		return true
1259
+	})
1260
+
1261
+	return &Value{data: groups}
1262
+
1263
+}
1264
+
1265
+// ReplaceInt32 uses the specified function to replace each int32s
1266
+// by iterating each item.  The data in the returned result will be a
1267
+// []int32 containing the replaced items.
1268
+func (v *Value) ReplaceInt32(replacer func(int, int32) int32) *Value {
1269
+
1270
+	arr := v.MustInt32Slice()
1271
+	replaced := make([]int32, len(arr))
1272
+
1273
+	v.EachInt32(func(index int, val int32) bool {
1274
+		replaced[index] = replacer(index, val)
1275
+		return true
1276
+	})
1277
+
1278
+	return &Value{data: replaced}
1279
+
1280
+}
1281
+
1282
+// CollectInt32 uses the specified collector function to collect a value
1283
+// for each of the int32s in the slice.  The data returned will be a
1284
+// []interface{}.
1285
+func (v *Value) CollectInt32(collector func(int, int32) interface{}) *Value {
1286
+
1287
+	arr := v.MustInt32Slice()
1288
+	collected := make([]interface{}, len(arr))
1289
+
1290
+	v.EachInt32(func(index int, val int32) bool {
1291
+		collected[index] = collector(index, val)
1292
+		return true
1293
+	})
1294
+
1295
+	return &Value{data: collected}
1296
+}
1297
+
1298
+/*
1299
+	Int64 (int64 and []int64)
1300
+	--------------------------------------------------
1301
+*/
1302
+
1303
+// Int64 gets the value as a int64, returns the optionalDefault
1304
+// value or a system default object if the value is the wrong type.
1305
+func (v *Value) Int64(optionalDefault ...int64) int64 {
1306
+	if s, ok := v.data.(int64); ok {
1307
+		return s
1308
+	}
1309
+	if len(optionalDefault) == 1 {
1310
+		return optionalDefault[0]
1311
+	}
1312
+	return 0
1313
+}
1314
+
1315
+// MustInt64 gets the value as a int64.
1316
+//
1317
+// Panics if the object is not a int64.
1318
+func (v *Value) MustInt64() int64 {
1319
+	return v.data.(int64)
1320
+}
1321
+
1322
+// Int64Slice gets the value as a []int64, returns the optionalDefault
1323
+// value or nil if the value is not a []int64.
1324
+func (v *Value) Int64Slice(optionalDefault ...[]int64) []int64 {
1325
+	if s, ok := v.data.([]int64); ok {
1326
+		return s
1327
+	}
1328
+	if len(optionalDefault) == 1 {
1329
+		return optionalDefault[0]
1330
+	}
1331
+	return nil
1332
+}
1333
+
1334
+// MustInt64Slice gets the value as a []int64.
1335
+//
1336
+// Panics if the object is not a []int64.
1337
+func (v *Value) MustInt64Slice() []int64 {
1338
+	return v.data.([]int64)
1339
+}
1340
+
1341
+// IsInt64 gets whether the object contained is a int64 or not.
1342
+func (v *Value) IsInt64() bool {
1343
+	_, ok := v.data.(int64)
1344
+	return ok
1345
+}
1346
+
1347
+// IsInt64Slice gets whether the object contained is a []int64 or not.
1348
+func (v *Value) IsInt64Slice() bool {
1349
+	_, ok := v.data.([]int64)
1350
+	return ok
1351
+}
1352
+
1353
+// EachInt64 calls the specified callback for each object
1354
+// in the []int64.
1355
+//
1356
+// Panics if the object is the wrong type.
1357
+func (v *Value) EachInt64(callback func(int, int64) bool) *Value {
1358
+
1359
+	for index, val := range v.MustInt64Slice() {
1360
+		carryon := callback(index, val)
1361
+		if carryon == false {
1362
+			break
1363
+		}
1364
+	}
1365
+
1366
+	return v
1367
+
1368
+}
1369
+
1370
+// WhereInt64 uses the specified decider function to select items
1371
+// from the []int64.  The object contained in the result will contain
1372
+// only the selected items.
1373
+func (v *Value) WhereInt64(decider func(int, int64) bool) *Value {
1374
+
1375
+	var selected []int64
1376
+
1377
+	v.EachInt64(func(index int, val int64) bool {
1378
+		shouldSelect := decider(index, val)
1379
+		if shouldSelect == false {
1380
+			selected = append(selected, val)
1381
+		}
1382
+		return true
1383
+	})
1384
+
1385
+	return &Value{data: selected}
1386
+
1387
+}
1388
+
1389
+// GroupInt64 uses the specified grouper function to group the items
1390
+// keyed by the return of the grouper.  The object contained in the
1391
+// result will contain a map[string][]int64.
1392
+func (v *Value) GroupInt64(grouper func(int, int64) string) *Value {
1393
+
1394
+	groups := make(map[string][]int64)
1395
+
1396
+	v.EachInt64(func(index int, val int64) bool {
1397
+		group := grouper(index, val)
1398
+		if _, ok := groups[group]; !ok {
1399
+			groups[group] = make([]int64, 0)
1400
+		}
1401
+		groups[group] = append(groups[group], val)
1402
+		return true
1403
+	})
1404
+
1405
+	return &Value{data: groups}
1406
+
1407
+}
1408
+
1409
+// ReplaceInt64 uses the specified function to replace each int64s
1410
+// by iterating each item.  The data in the returned result will be a
1411
+// []int64 containing the replaced items.
1412
+func (v *Value) ReplaceInt64(replacer func(int, int64) int64) *Value {
1413
+
1414
+	arr := v.MustInt64Slice()
1415
+	replaced := make([]int64, len(arr))
1416
+
1417
+	v.EachInt64(func(index int, val int64) bool {
1418
+		replaced[index] = replacer(index, val)
1419
+		return true
1420
+	})
1421
+
1422
+	return &Value{data: replaced}
1423
+
1424
+}
1425
+
1426
+// CollectInt64 uses the specified collector function to collect a value
1427
+// for each of the int64s in the slice.  The data returned will be a
1428
+// []interface{}.
1429
+func (v *Value) CollectInt64(collector func(int, int64) interface{}) *Value {
1430
+
1431
+	arr := v.MustInt64Slice()
1432
+	collected := make([]interface{}, len(arr))
1433
+
1434
+	v.EachInt64(func(index int, val int64) bool {
1435
+		collected[index] = collector(index, val)
1436
+		return true
1437
+	})
1438
+
1439
+	return &Value{data: collected}
1440
+}
1441
+
1442
+/*
1443
+	Uint (uint and []uint)
1444
+	--------------------------------------------------
1445
+*/
1446
+
1447
+// Uint gets the value as a uint, returns the optionalDefault
1448
+// value or a system default object if the value is the wrong type.
1449
+func (v *Value) Uint(optionalDefault ...uint) uint {
1450
+	if s, ok := v.data.(uint); ok {
1451
+		return s
1452
+	}
1453
+	if len(optionalDefault) == 1 {
1454
+		return optionalDefault[0]
1455
+	}
1456
+	return 0
1457
+}
1458
+
1459
+// MustUint gets the value as a uint.
1460
+//
1461
+// Panics if the object is not a uint.
1462
+func (v *Value) MustUint() uint {
1463
+	return v.data.(uint)
1464
+}
1465
+
1466
+// UintSlice gets the value as a []uint, returns the optionalDefault
1467
+// value or nil if the value is not a []uint.
1468
+func (v *Value) UintSlice(optionalDefault ...[]uint) []uint {
1469
+	if s, ok := v.data.([]uint); ok {
1470
+		return s
1471
+	}
1472
+	if len(optionalDefault) == 1 {
1473
+		return optionalDefault[0]
1474
+	}
1475
+	return nil
1476
+}
1477
+
1478
+// MustUintSlice gets the value as a []uint.
1479
+//
1480
+// Panics if the object is not a []uint.
1481
+func (v *Value) MustUintSlice() []uint {
1482
+	return v.data.([]uint)
1483
+}
1484
+
1485
+// IsUint gets whether the object contained is a uint or not.
1486
+func (v *Value) IsUint() bool {
1487
+	_, ok := v.data.(uint)
1488
+	return ok
1489
+}
1490
+
1491
+// IsUintSlice gets whether the object contained is a []uint or not.
1492
+func (v *Value) IsUintSlice() bool {
1493
+	_, ok := v.data.([]uint)
1494
+	return ok
1495
+}
1496
+
1497
+// EachUint calls the specified callback for each object
1498
+// in the []uint.
1499
+//
1500
+// Panics if the object is the wrong type.
1501
+func (v *Value) EachUint(callback func(int, uint) bool) *Value {
1502
+
1503
+	for index, val := range v.MustUintSlice() {
1504
+		carryon := callback(index, val)
1505
+		if carryon == false {
1506
+			break
1507
+		}
1508
+	}
1509
+
1510
+	return v
1511
+
1512
+}
1513
+
1514
+// WhereUint uses the specified decider function to select items
1515
+// from the []uint.  The object contained in the result will contain
1516
+// only the selected items.
1517
+func (v *Value) WhereUint(decider func(int, uint) bool) *Value {
1518
+
1519
+	var selected []uint
1520
+
1521
+	v.EachUint(func(index int, val uint) bool {
1522
+		shouldSelect := decider(index, val)
1523
+		if shouldSelect == false {
1524
+			selected = append(selected, val)
1525
+		}
1526
+		return true
1527
+	})
1528
+
1529
+	return &Value{data: selected}
1530
+
1531
+}
1532
+
1533
+// GroupUint uses the specified grouper function to group the items
1534
+// keyed by the return of the grouper.  The object contained in the
1535
+// result will contain a map[string][]uint.
1536
+func (v *Value) GroupUint(grouper func(int, uint) string) *Value {
1537
+
1538
+	groups := make(map[string][]uint)
1539
+
1540
+	v.EachUint(func(index int, val uint) bool {
1541
+		group := grouper(index, val)
1542
+		if _, ok := groups[group]; !ok {
1543
+			groups[group] = make([]uint, 0)
1544
+		}
1545
+		groups[group] = append(groups[group], val)
1546
+		return true
1547
+	})
1548
+
1549
+	return &Value{data: groups}
1550
+
1551
+}
1552
+
1553
+// ReplaceUint uses the specified function to replace each uints
1554
+// by iterating each item.  The data in the returned result will be a
1555
+// []uint containing the replaced items.
1556
+func (v *Value) ReplaceUint(replacer func(int, uint) uint) *Value {
1557
+
1558
+	arr := v.MustUintSlice()
1559
+	replaced := make([]uint, len(arr))
1560
+
1561
+	v.EachUint(func(index int, val uint) bool {
1562
+		replaced[index] = replacer(index, val)
1563
+		return true
1564
+	})
1565
+
1566
+	return &Value{data: replaced}
1567
+
1568
+}
1569
+
1570
+// CollectUint uses the specified collector function to collect a value
1571
+// for each of the uints in the slice.  The data returned will be a
1572
+// []interface{}.
1573
+func (v *Value) CollectUint(collector func(int, uint) interface{}) *Value {
1574
+
1575
+	arr := v.MustUintSlice()
1576
+	collected := make([]interface{}, len(arr))
1577
+
1578
+	v.EachUint(func(index int, val uint) bool {
1579
+		collected[index] = collector(index, val)
1580
+		return true
1581
+	})
1582
+
1583
+	return &Value{data: collected}
1584
+}
1585
+
1586
+/*
1587
+	Uint8 (uint8 and []uint8)
1588
+	--------------------------------------------------
1589
+*/
1590
+
1591
+// Uint8 gets the value as a uint8, returns the optionalDefault
1592
+// value or a system default object if the value is the wrong type.
1593
+func (v *Value) Uint8(optionalDefault ...uint8) uint8 {
1594
+	if s, ok := v.data.(uint8); ok {
1595
+		return s
1596
+	}
1597
+	if len(optionalDefault) == 1 {
1598
+		return optionalDefault[0]
1599
+	}
1600
+	return 0
1601
+}
1602
+
1603
+// MustUint8 gets the value as a uint8.
1604
+//
1605
+// Panics if the object is not a uint8.
1606
+func (v *Value) MustUint8() uint8 {
1607
+	return v.data.(uint8)
1608
+}
1609
+
1610
+// Uint8Slice gets the value as a []uint8, returns the optionalDefault
1611
+// value or nil if the value is not a []uint8.
1612
+func (v *Value) Uint8Slice(optionalDefault ...[]uint8) []uint8 {
1613
+	if s, ok := v.data.([]uint8); ok {
1614
+		return s
1615
+	}
1616
+	if len(optionalDefault) == 1 {
1617
+		return optionalDefault[0]
1618
+	}
1619
+	return nil
1620
+}
1621
+
1622
+// MustUint8Slice gets the value as a []uint8.
1623
+//
1624
+// Panics if the object is not a []uint8.
1625
+func (v *Value) MustUint8Slice() []uint8 {
1626
+	return v.data.([]uint8)
1627
+}
1628
+
1629
+// IsUint8 gets whether the object contained is a uint8 or not.
1630
+func (v *Value) IsUint8() bool {
1631
+	_, ok := v.data.(uint8)
1632
+	return ok
1633
+}
1634
+
1635
+// IsUint8Slice gets whether the object contained is a []uint8 or not.
1636
+func (v *Value) IsUint8Slice() bool {
1637
+	_, ok := v.data.([]uint8)
1638
+	return ok
1639
+}
1640
+
1641
+// EachUint8 calls the specified callback for each object
1642
+// in the []uint8.
1643
+//
1644
+// Panics if the object is the wrong type.
1645
+func (v *Value) EachUint8(callback func(int, uint8) bool) *Value {
1646
+
1647
+	for index, val := range v.MustUint8Slice() {
1648
+		carryon := callback(index, val)
1649
+		if carryon == false {
1650
+			break
1651
+		}
1652
+	}
1653
+
1654
+	return v
1655
+
1656
+}
1657
+
1658
+// WhereUint8 uses the specified decider function to select items
1659
+// from the []uint8.  The object contained in the result will contain
1660
+// only the selected items.
1661
+func (v *Value) WhereUint8(decider func(int, uint8) bool) *Value {
1662
+
1663
+	var selected []uint8
1664
+
1665
+	v.EachUint8(func(index int, val uint8) bool {
1666
+		shouldSelect := decider(index, val)
1667
+		if shouldSelect == false {
1668
+			selected = append(selected, val)
1669
+		}
1670
+		return true
1671
+	})
1672
+
1673
+	return &Value{data: selected}
1674
+
1675
+}
1676
+
1677
+// GroupUint8 uses the specified grouper function to group the items
1678
+// keyed by the return of the grouper.  The object contained in the
1679
+// result will contain a map[string][]uint8.
1680
+func (v *Value) GroupUint8(grouper func(int, uint8) string) *Value {
1681
+
1682
+	groups := make(map[string][]uint8)
1683
+
1684
+	v.EachUint8(func(index int, val uint8) bool {
1685
+		group := grouper(index, val)
1686
+		if _, ok := groups[group]; !ok {
1687
+			groups[group] = make([]uint8, 0)
1688
+		}
1689
+		groups[group] = append(groups[group], val)
1690
+		return true
1691
+	})
1692
+
1693
+	return &Value{data: groups}
1694
+
1695
+}
1696
+
1697
+// ReplaceUint8 uses the specified function to replace each uint8s
1698
+// by iterating each item.  The data in the returned result will be a
1699
+// []uint8 containing the replaced items.
1700
+func (v *Value) ReplaceUint8(replacer func(int, uint8) uint8) *Value {
1701
+
1702
+	arr := v.MustUint8Slice()
1703
+	replaced := make([]uint8, len(arr))
1704
+
1705
+	v.EachUint8(func(index int, val uint8) bool {
1706
+		replaced[index] = replacer(index, val)
1707
+		return true
1708
+	})
1709
+
1710
+	return &Value{data: replaced}
1711
+
1712
+}
1713
+
1714
+// CollectUint8 uses the specified collector function to collect a value
1715
+// for each of the uint8s in the slice.  The data returned will be a
1716
+// []interface{}.
1717
+func (v *Value) CollectUint8(collector func(int, uint8) interface{}) *Value {
1718
+
1719
+	arr := v.MustUint8Slice()
1720
+	collected := make([]interface{}, len(arr))
1721
+
1722
+	v.EachUint8(func(index int, val uint8) bool {
1723
+		collected[index] = collector(index, val)
1724
+		return true
1725
+	})
1726
+
1727
+	return &Value{data: collected}
1728
+}
1729
+
1730
+/*
1731
+	Uint16 (uint16 and []uint16)
1732
+	--------------------------------------------------
1733
+*/
1734
+
1735
+// Uint16 gets the value as a uint16, returns the optionalDefault
1736
+// value or a system default object if the value is the wrong type.
1737
+func (v *Value) Uint16(optionalDefault ...uint16) uint16 {
1738
+	if s, ok := v.data.(uint16); ok {
1739
+		return s
1740
+	}
1741
+	if len(optionalDefault) == 1 {
1742
+		return optionalDefault[0]
1743
+	}
1744
+	return 0
1745
+}
1746
+
1747
+// MustUint16 gets the value as a uint16.
1748
+//
1749
+// Panics if the object is not a uint16.
1750
+func (v *Value) MustUint16() uint16 {
1751
+	return v.data.(uint16)
1752
+}
1753
+
1754
+// Uint16Slice gets the value as a []uint16, returns the optionalDefault
1755
+// value or nil if the value is not a []uint16.
1756
+func (v *Value) Uint16Slice(optionalDefault ...[]uint16) []uint16 {
1757
+	if s, ok := v.data.([]uint16); ok {
1758
+		return s
1759
+	}
1760
+	if len(optionalDefault) == 1 {
1761
+		return optionalDefault[0]
1762
+	}
1763
+	return nil
1764
+}
1765
+
1766
+// MustUint16Slice gets the value as a []uint16.
1767
+//
1768
+// Panics if the object is not a []uint16.
1769
+func (v *Value) MustUint16Slice() []uint16 {
1770
+	return v.data.([]uint16)
1771
+}
1772
+
1773
+// IsUint16 gets whether the object contained is a uint16 or not.
1774
+func (v *Value) IsUint16() bool {
1775
+	_, ok := v.data.(uint16)
1776
+	return ok
1777
+}
1778
+
1779
+// IsUint16Slice gets whether the object contained is a []uint16 or not.
1780
+func (v *Value) IsUint16Slice() bool {
1781
+	_, ok := v.data.([]uint16)
1782
+	return ok
1783
+}
1784
+
1785
+// EachUint16 calls the specified callback for each object
1786
+// in the []uint16.
1787
+//
1788
+// Panics if the object is the wrong type.
1789
+func (v *Value) EachUint16(callback func(int, uint16) bool) *Value {
1790
+
1791
+	for index, val := range v.MustUint16Slice() {
1792
+		carryon := callback(index, val)
1793
+		if carryon == false {
1794
+			break
1795
+		}
1796
+	}
1797
+
1798
+	return v
1799
+
1800
+}
1801
+
1802
+// WhereUint16 uses the specified decider function to select items
1803
+// from the []uint16.  The object contained in the result will contain
1804
+// only the selected items.
1805
+func (v *Value) WhereUint16(decider func(int, uint16) bool) *Value {
1806
+
1807
+	var selected []uint16
1808
+
1809
+	v.EachUint16(func(index int, val uint16) bool {
1810
+		shouldSelect := decider(index, val)
1811
+		if shouldSelect == false {
1812
+			selected = append(selected, val)
1813
+		}
1814
+		return true
1815
+	})
1816
+
1817
+	return &Value{data: selected}
1818
+
1819
+}
1820
+
1821
+// GroupUint16 uses the specified grouper function to group the items
1822
+// keyed by the return of the grouper.  The object contained in the
1823
+// result will contain a map[string][]uint16.
1824
+func (v *Value) GroupUint16(grouper func(int, uint16) string) *Value {
1825
+
1826
+	groups := make(map[string][]uint16)
1827
+
1828
+	v.EachUint16(func(index int, val uint16) bool {
1829
+		group := grouper(index, val)
1830
+		if _, ok := groups[group]; !ok {
1831
+			groups[group] = make([]uint16, 0)
1832
+		}
1833
+		groups[group] = append(groups[group], val)
1834
+		return true
1835
+	})
1836
+
1837
+	return &Value{data: groups}
1838
+
1839
+}
1840
+
1841
+// ReplaceUint16 uses the specified function to replace each uint16s
1842
+// by iterating each item.  The data in the returned result will be a
1843
+// []uint16 containing the replaced items.
1844
+func (v *Value) ReplaceUint16(replacer func(int, uint16) uint16) *Value {
1845
+
1846
+	arr := v.MustUint16Slice()
1847
+	replaced := make([]uint16, len(arr))
1848
+
1849
+	v.EachUint16(func(index int, val uint16) bool {
1850
+		replaced[index] = replacer(index, val)
1851
+		return true
1852
+	})
1853
+
1854
+	return &Value{data: replaced}
1855
+
1856
+}
1857
+
1858
+// CollectUint16 uses the specified collector function to collect a value
1859
+// for each of the uint16s in the slice.  The data returned will be a
1860
+// []interface{}.
1861
+func (v *Value) CollectUint16(collector func(int, uint16) interface{}) *Value {
1862
+
1863
+	arr := v.MustUint16Slice()
1864
+	collected := make([]interface{}, len(arr))
1865
+
1866
+	v.EachUint16(func(index int, val uint16) bool {
1867
+		collected[index] = collector(index, val)
1868
+		return true
1869
+	})
1870
+
1871
+	return &Value{data: collected}
1872
+}
1873
+
1874
+/*
1875
+	Uint32 (uint32 and []uint32)
1876
+	--------------------------------------------------
1877
+*/
1878
+
1879
+// Uint32 gets the value as a uint32, returns the optionalDefault
1880
+// value or a system default object if the value is the wrong type.
1881
+func (v *Value) Uint32(optionalDefault ...uint32) uint32 {
1882
+	if s, ok := v.data.(uint32); ok {
1883
+		return s
1884
+	}
1885
+	if len(optionalDefault) == 1 {
1886
+		return optionalDefault[0]
1887
+	}
1888
+	return 0
1889
+}
1890
+
1891
+// MustUint32 gets the value as a uint32.
1892
+//
1893
+// Panics if the object is not a uint32.
1894
+func (v *Value) MustUint32() uint32 {
1895
+	return v.data.(uint32)
1896
+}
1897
+
1898
+// Uint32Slice gets the value as a []uint32, returns the optionalDefault
1899
+// value or nil if the value is not a []uint32.
1900
+func (v *Value) Uint32Slice(optionalDefault ...[]uint32) []uint32 {
1901
+	if s, ok := v.data.([]uint32); ok {
1902
+		return s
1903
+	}
1904
+	if len(optionalDefault) == 1 {
1905
+		return optionalDefault[0]
1906
+	}
1907
+	return nil
1908
+}
1909
+
1910
+// MustUint32Slice gets the value as a []uint32.
1911
+//
1912
+// Panics if the object is not a []uint32.
1913
+func (v *Value) MustUint32Slice() []uint32 {
1914
+	return v.data.([]uint32)
1915
+}
1916
+
1917
+// IsUint32 gets whether the object contained is a uint32 or not.
1918
+func (v *Value) IsUint32() bool {
1919
+	_, ok := v.data.(uint32)
1920
+	return ok
1921
+}
1922
+
1923
+// IsUint32Slice gets whether the object contained is a []uint32 or not.
1924
+func (v *Value) IsUint32Slice() bool {
1925
+	_, ok := v.data.([]uint32)
1926
+	return ok
1927
+}
1928
+
1929
+// EachUint32 calls the specified callback for each object
1930
+// in the []uint32.
1931
+//
1932
+// Panics if the object is the wrong type.
1933
+func (v *Value) EachUint32(callback func(int, uint32) bool) *Value {
1934
+
1935
+	for index, val := range v.MustUint32Slice() {
1936
+		carryon := callback(index, val)
1937
+		if carryon == false {
1938
+			break
1939
+		}
1940
+	}
1941
+
1942
+	return v
1943
+
1944
+}
1945
+
1946
+// WhereUint32 uses the specified decider function to select items
1947
+// from the []uint32.  The object contained in the result will contain
1948
+// only the selected items.
1949
+func (v *Value) WhereUint32(decider func(int, uint32) bool) *Value {
1950
+
1951
+	var selected []uint32
1952
+
1953
+	v.EachUint32(func(index int, val uint32) bool {
1954
+		shouldSelect := decider(index, val)
1955
+		if shouldSelect == false {
1956
+			selected = append(selected, val)
1957
+		}
1958
+		return true
1959
+	})
1960
+
1961
+	return &Value{data: selected}
1962
+
1963
+}
1964
+
1965
+// GroupUint32 uses the specified grouper function to group the items
1966
+// keyed by the return of the grouper.  The object contained in the
1967
+// result will contain a map[string][]uint32.
1968
+func (v *Value) GroupUint32(grouper func(int, uint32) string) *Value {
1969
+
1970
+	groups := make(map[string][]uint32)
1971
+
1972
+	v.EachUint32(func(index int, val uint32) bool {
1973
+		group := grouper(index, val)
1974
+		if _, ok := groups[group]; !ok {
1975
+			groups[group] = make([]uint32, 0)
1976
+		}
1977
+		groups[group] = append(groups[group], val)
1978
+		return true
1979
+	})
1980
+
1981
+	return &Value{data: groups}
1982
+
1983
+}
1984
+
1985
+// ReplaceUint32 uses the specified function to replace each uint32s
1986
+// by iterating each item.  The data in the returned result will be a
1987
+// []uint32 containing the replaced items.
1988
+func (v *Value) ReplaceUint32(replacer func(int, uint32) uint32) *Value {
1989
+
1990
+	arr := v.MustUint32Slice()
1991
+	replaced := make([]uint32, len(arr))
1992
+
1993
+	v.EachUint32(func(index int, val uint32) bool {
1994
+		replaced[index] = replacer(index, val)
1995
+		return true
1996
+	})
1997
+
1998
+	return &Value{data: replaced}
1999
+
2000
+}
2001
+
2002
+// CollectUint32 uses the specified collector function to collect a value
2003
+// for each of the uint32s in the slice.  The data returned will be a
2004
+// []interface{}.
2005
+func (v *Value) CollectUint32(collector func(int, uint32) interface{}) *Value {
2006
+
2007
+	arr := v.MustUint32Slice()
2008
+	collected := make([]interface{}, len(arr))
2009
+
2010
+	v.EachUint32(func(index int, val uint32) bool {
2011
+		collected[index] = collector(index, val)
2012
+		return true
2013
+	})
2014
+
2015
+	return &Value{data: collected}
2016
+}
2017
+
2018
+/*
2019
+	Uint64 (uint64 and []uint64)
2020
+	--------------------------------------------------
2021
+*/
2022
+
2023
+// Uint64 gets the value as a uint64, returns the optionalDefault
2024
+// value or a system default object if the value is the wrong type.
2025
+func (v *Value) Uint64(optionalDefault ...uint64) uint64 {
2026
+	if s, ok := v.data.(uint64); ok {
2027
+		return s
2028
+	}
2029
+	if len(optionalDefault) == 1 {
2030
+		return optionalDefault[0]
2031
+	}
2032
+	return 0
2033
+}
2034
+
2035
+// MustUint64 gets the value as a uint64.
2036
+//
2037
+// Panics if the object is not a uint64.
2038
+func (v *Value) MustUint64() uint64 {
2039
+	return v.data.(uint64)
2040
+}
2041
+
2042
+// Uint64Slice gets the value as a []uint64, returns the optionalDefault
2043
+// value or nil if the value is not a []uint64.
2044
+func (v *Value) Uint64Slice(optionalDefault ...[]uint64) []uint64 {
2045
+	if s, ok := v.data.([]uint64); ok {
2046
+		return s
2047
+	}
2048
+	if len(optionalDefault) == 1 {
2049
+		return optionalDefault[0]
2050
+	}
2051
+	return nil
2052
+}
2053
+
2054
+// MustUint64Slice gets the value as a []uint64.
2055
+//
2056
+// Panics if the object is not a []uint64.
2057
+func (v *Value) MustUint64Slice() []uint64 {
2058
+	return v.data.([]uint64)
2059
+}
2060
+
2061
+// IsUint64 gets whether the object contained is a uint64 or not.
2062
+func (v *Value) IsUint64() bool {
2063
+	_, ok := v.data.(uint64)
2064
+	return ok
2065
+}
2066
+
2067
+// IsUint64Slice gets whether the object contained is a []uint64 or not.
2068
+func (v *Value) IsUint64Slice() bool {
2069
+	_, ok := v.data.([]uint64)
2070
+	return ok
2071
+}
2072
+
2073
+// EachUint64 calls the specified callback for each object
2074
+// in the []uint64.
2075
+//
2076
+// Panics if the object is the wrong type.
2077
+func (v *Value) EachUint64(callback func(int, uint64) bool) *Value {
2078
+
2079
+	for index, val := range v.MustUint64Slice() {
2080
+		carryon := callback(index, val)
2081
+		if carryon == false {
2082
+			break
2083
+		}
2084
+	}
2085
+
2086
+	return v
2087
+
2088
+}
2089
+
2090
+// WhereUint64 uses the specified decider function to select items
2091
+// from the []uint64.  The object contained in the result will contain
2092
+// only the selected items.
2093
+func (v *Value) WhereUint64(decider func(int, uint64) bool) *Value {
2094
+
2095
+	var selected []uint64
2096
+
2097
+	v.EachUint64(func(index int, val uint64) bool {
2098
+		shouldSelect := decider(index, val)
2099
+		if shouldSelect == false {
2100
+			selected = append(selected, val)
2101
+		}
2102
+		return true
2103
+	})
2104
+
2105
+	return &Value{data: selected}
2106
+
2107
+}
2108
+
2109
+// GroupUint64 uses the specified grouper function to group the items
2110
+// keyed by the return of the grouper.  The object contained in the
2111
+// result will contain a map[string][]uint64.
2112
+func (v *Value) GroupUint64(grouper func(int, uint64) string) *Value {
2113
+
2114
+	groups := make(map[string][]uint64)
2115
+
2116
+	v.EachUint64(func(index int, val uint64) bool {
2117
+		group := grouper(index, val)
2118
+		if _, ok := groups[group]; !ok {
2119
+			groups[group] = make([]uint64, 0)
2120
+		}
2121
+		groups[group] = append(groups[group], val)
2122
+		return true
2123
+	})
2124
+
2125
+	return &Value{data: groups}
2126
+
2127
+}
2128
+
2129
+// ReplaceUint64 uses the specified function to replace each uint64s
2130
+// by iterating each item.  The data in the returned result will be a
2131
+// []uint64 containing the replaced items.
2132
+func (v *Value) ReplaceUint64(replacer func(int, uint64) uint64) *Value {
2133
+
2134
+	arr := v.MustUint64Slice()
2135
+	replaced := make([]uint64, len(arr))
2136
+
2137
+	v.EachUint64(func(index int, val uint64) bool {
2138
+		replaced[index] = replacer(index, val)
2139
+		return true
2140
+	})
2141
+
2142
+	return &Value{data: replaced}
2143
+
2144
+}
2145
+
2146
+// CollectUint64 uses the specified collector function to collect a value
2147
+// for each of the uint64s in the slice.  The data returned will be a
2148
+// []interface{}.
2149
+func (v *Value) CollectUint64(collector func(int, uint64) interface{}) *Value {
2150
+
2151
+	arr := v.MustUint64Slice()
2152
+	collected := make([]interface{}, len(arr))
2153
+
2154
+	v.EachUint64(func(index int, val uint64) bool {
2155
+		collected[index] = collector(index, val)
2156
+		return true
2157
+	})
2158
+
2159
+	return &Value{data: collected}
2160
+}
2161
+
2162
+/*
2163
+	Uintptr (uintptr and []uintptr)
2164
+	--------------------------------------------------
2165
+*/
2166
+
2167
+// Uintptr gets the value as a uintptr, returns the optionalDefault
2168
+// value or a system default object if the value is the wrong type.
2169
+func (v *Value) Uintptr(optionalDefault ...uintptr) uintptr {
2170
+	if s, ok := v.data.(uintptr); ok {
2171
+		return s
2172
+	}
2173
+	if len(optionalDefault) == 1 {
2174
+		return optionalDefault[0]
2175
+	}
2176
+	return 0
2177
+}
2178
+
2179
+// MustUintptr gets the value as a uintptr.
2180
+//
2181
+// Panics if the object is not a uintptr.
2182
+func (v *Value) MustUintptr() uintptr {
2183
+	return v.data.(uintptr)
2184
+}
2185
+
2186
+// UintptrSlice gets the value as a []uintptr, returns the optionalDefault
2187
+// value or nil if the value is not a []uintptr.
2188
+func (v *Value) UintptrSlice(optionalDefault ...[]uintptr) []uintptr {
2189
+	if s, ok := v.data.([]uintptr); ok {
2190
+		return s
2191
+	}
2192
+	if len(optionalDefault) == 1 {
2193
+		return optionalDefault[0]
2194
+	}
2195
+	return nil
2196
+}
2197
+
2198
+// MustUintptrSlice gets the value as a []uintptr.
2199
+//
2200
+// Panics if the object is not a []uintptr.
2201
+func (v *Value) MustUintptrSlice() []uintptr {
2202
+	return v.data.([]uintptr)
2203
+}
2204
+
2205
+// IsUintptr gets whether the object contained is a uintptr or not.
2206
+func (v *Value) IsUintptr() bool {
2207
+	_, ok := v.data.(uintptr)
2208
+	return ok
2209
+}
2210
+
2211
+// IsUintptrSlice gets whether the object contained is a []uintptr or not.
2212
+func (v *Value) IsUintptrSlice() bool {
2213
+	_, ok := v.data.([]uintptr)
2214
+	return ok
2215
+}
2216
+
2217
+// EachUintptr calls the specified callback for each object
2218
+// in the []uintptr.
2219
+//
2220
+// Panics if the object is the wrong type.
2221
+func (v *Value) EachUintptr(callback func(int, uintptr) bool) *Value {
2222
+
2223
+	for index, val := range v.MustUintptrSlice() {
2224
+		carryon := callback(index, val)
2225
+		if carryon == false {
2226
+			break
2227
+		}
2228
+	}
2229
+
2230
+	return v
2231
+
2232
+}
2233
+
2234
+// WhereUintptr uses the specified decider function to select items
2235
+// from the []uintptr.  The object contained in the result will contain
2236
+// only the selected items.
2237
+func (v *Value) WhereUintptr(decider func(int, uintptr) bool) *Value {
2238
+
2239
+	var selected []uintptr
2240
+
2241
+	v.EachUintptr(func(index int, val uintptr) bool {
2242
+		shouldSelect := decider(index, val)
2243
+		if shouldSelect == false {
2244
+			selected = append(selected, val)
2245
+		}
2246
+		return true
2247
+	})
2248
+
2249
+	return &Value{data: selected}
2250
+
2251
+}
2252
+
2253
+// GroupUintptr uses the specified grouper function to group the items
2254
+// keyed by the return of the grouper.  The object contained in the
2255
+// result will contain a map[string][]uintptr.
2256
+func (v *Value) GroupUintptr(grouper func(int, uintptr) string) *Value {
2257
+
2258
+	groups := make(map[string][]uintptr)
2259
+
2260
+	v.EachUintptr(func(index int, val uintptr) bool {
2261
+		group := grouper(index, val)
2262
+		if _, ok := groups[group]; !ok {
2263
+			groups[group] = make([]uintptr, 0)
2264
+		}
2265
+		groups[group] = append(groups[group], val)
2266
+		return true
2267
+	})
2268
+
2269
+	return &Value{data: groups}
2270
+
2271
+}
2272
+
2273
+// ReplaceUintptr uses the specified function to replace each uintptrs
2274
+// by iterating each item.  The data in the returned result will be a
2275
+// []uintptr containing the replaced items.
2276
+func (v *Value) ReplaceUintptr(replacer func(int, uintptr) uintptr) *Value {
2277
+
2278
+	arr := v.MustUintptrSlice()
2279
+	replaced := make([]uintptr, len(arr))
2280
+
2281
+	v.EachUintptr(func(index int, val uintptr) bool {
2282
+		replaced[index] = replacer(index, val)
2283
+		return true
2284
+	})
2285
+
2286
+	return &Value{data: replaced}
2287
+
2288
+}
2289
+
2290
+// CollectUintptr uses the specified collector function to collect a value
2291
+// for each of the uintptrs in the slice.  The data returned will be a
2292
+// []interface{}.
2293
+func (v *Value) CollectUintptr(collector func(int, uintptr) interface{}) *Value {
2294
+
2295
+	arr := v.MustUintptrSlice()
2296
+	collected := make([]interface{}, len(arr))
2297
+
2298
+	v.EachUintptr(func(index int, val uintptr) bool {
2299
+		collected[index] = collector(index, val)
2300
+		return true
2301
+	})
2302
+
2303
+	return &Value{data: collected}
2304
+}
2305
+
2306
+/*
2307
+	Float32 (float32 and []float32)
2308
+	--------------------------------------------------
2309
+*/
2310
+
2311
+// Float32 gets the value as a float32, returns the optionalDefault
2312
+// value or a system default object if the value is the wrong type.
2313
+func (v *Value) Float32(optionalDefault ...float32) float32 {
2314
+	if s, ok := v.data.(float32); ok {
2315
+		return s
2316
+	}
2317
+	if len(optionalDefault) == 1 {
2318
+		return optionalDefault[0]
2319
+	}
2320
+	return 0
2321
+}
2322
+
2323
+// MustFloat32 gets the value as a float32.
2324
+//
2325
+// Panics if the object is not a float32.
2326
+func (v *Value) MustFloat32() float32 {
2327
+	return v.data.(float32)
2328
+}
2329
+
2330
+// Float32Slice gets the value as a []float32, returns the optionalDefault
2331
+// value or nil if the value is not a []float32.
2332
+func (v *Value) Float32Slice(optionalDefault ...[]float32) []float32 {
2333
+	if s, ok := v.data.([]float32); ok {
2334
+		return s
2335
+	}
2336
+	if len(optionalDefault) == 1 {
2337
+		return optionalDefault[0]
2338
+	}
2339
+	return nil
2340
+}
2341
+
2342
+// MustFloat32Slice gets the value as a []float32.
2343
+//
2344
+// Panics if the object is not a []float32.
2345
+func (v *Value) MustFloat32Slice() []float32 {
2346
+	return v.data.([]float32)
2347
+}
2348
+
2349
+// IsFloat32 gets whether the object contained is a float32 or not.
2350
+func (v *Value) IsFloat32() bool {
2351
+	_, ok := v.data.(float32)
2352
+	return ok
2353
+}
2354
+
2355
+// IsFloat32Slice gets whether the object contained is a []float32 or not.
2356
+func (v *Value) IsFloat32Slice() bool {
2357
+	_, ok := v.data.([]float32)
2358
+	return ok
2359
+}
2360
+
2361
+// EachFloat32 calls the specified callback for each object
2362
+// in the []float32.
2363
+//
2364
+// Panics if the object is the wrong type.
2365
+func (v *Value) EachFloat32(callback func(int, float32) bool) *Value {
2366
+
2367
+	for index, val := range v.MustFloat32Slice() {
2368
+		carryon := callback(index, val)
2369
+		if carryon == false {
2370
+			break
2371
+		}
2372
+	}
2373
+
2374
+	return v
2375
+
2376
+}
2377
+
2378
+// WhereFloat32 uses the specified decider function to select items
2379
+// from the []float32.  The object contained in the result will contain
2380
+// only the selected items.
2381
+func (v *Value) WhereFloat32(decider func(int, float32) bool) *Value {
2382
+
2383
+	var selected []float32
2384
+
2385
+	v.EachFloat32(func(index int, val float32) bool {
2386
+		shouldSelect := decider(index, val)
2387
+		if shouldSelect == false {
2388
+			selected = append(selected, val)
2389
+		}
2390
+		return true
2391
+	})
2392
+
2393
+	return &Value{data: selected}
2394
+
2395
+}
2396
+
2397
+// GroupFloat32 uses the specified grouper function to group the items
2398
+// keyed by the return of the grouper.  The object contained in the
2399
+// result will contain a map[string][]float32.
2400
+func (v *Value) GroupFloat32(grouper func(int, float32) string) *Value {
2401
+
2402
+	groups := make(map[string][]float32)
2403
+
2404
+	v.EachFloat32(func(index int, val float32) bool {
2405
+		group := grouper(index, val)
2406
+		if _, ok := groups[group]; !ok {
2407
+			groups[group] = make([]float32, 0)
2408
+		}
2409
+		groups[group] = append(groups[group], val)
2410
+		return true
2411
+	})
2412
+
2413
+	return &Value{data: groups}
2414
+
2415
+}
2416
+
2417
+// ReplaceFloat32 uses the specified function to replace each float32s
2418
+// by iterating each item.  The data in the returned result will be a
2419
+// []float32 containing the replaced items.
2420
+func (v *Value) ReplaceFloat32(replacer func(int, float32) float32) *Value {
2421
+
2422
+	arr := v.MustFloat32Slice()
2423
+	replaced := make([]float32, len(arr))
2424
+
2425
+	v.EachFloat32(func(index int, val float32) bool {
2426
+		replaced[index] = replacer(index, val)
2427
+		return true
2428
+	})
2429
+
2430
+	return &Value{data: replaced}
2431
+
2432
+}
2433
+
2434
+// CollectFloat32 uses the specified collector function to collect a value
2435
+// for each of the float32s in the slice.  The data returned will be a
2436
+// []interface{}.
2437
+func (v *Value) CollectFloat32(collector func(int, float32) interface{}) *Value {
2438
+
2439
+	arr := v.MustFloat32Slice()
2440
+	collected := make([]interface{}, len(arr))
2441
+
2442
+	v.EachFloat32(func(index int, val float32) bool {
2443
+		collected[index] = collector(index, val)
2444
+		return true
2445
+	})
2446
+
2447
+	return &Value{data: collected}
2448
+}
2449
+
2450
+/*
2451
+	Float64 (float64 and []float64)
2452
+	--------------------------------------------------
2453
+*/
2454
+
2455
+// Float64 gets the value as a float64, returns the optionalDefault
2456
+// value or a system default object if the value is the wrong type.
2457
+func (v *Value) Float64(optionalDefault ...float64) float64 {
2458
+	if s, ok := v.data.(float64); ok {
2459
+		return s
2460
+	}
2461
+	if len(optionalDefault) == 1 {
2462
+		return optionalDefault[0]
2463
+	}
2464
+	return 0
2465
+}
2466
+
2467
+// MustFloat64 gets the value as a float64.
2468
+//
2469
+// Panics if the object is not a float64.
2470
+func (v *Value) MustFloat64() float64 {
2471
+	return v.data.(float64)
2472
+}
2473
+
2474
+// Float64Slice gets the value as a []float64, returns the optionalDefault
2475
+// value or nil if the value is not a []float64.
2476
+func (v *Value) Float64Slice(optionalDefault ...[]float64) []float64 {
2477
+	if s, ok := v.data.([]float64); ok {
2478
+		return s
2479
+	}
2480
+	if len(optionalDefault) == 1 {
2481
+		return optionalDefault[0]
2482
+	}
2483
+	return nil
2484
+}
2485
+
2486
+// MustFloat64Slice gets the value as a []float64.
2487
+//
2488
+// Panics if the object is not a []float64.
2489
+func (v *Value) MustFloat64Slice() []float64 {
2490
+	return v.data.([]float64)
2491
+}
2492
+
2493
+// IsFloat64 gets whether the object contained is a float64 or not.
2494
+func (v *Value) IsFloat64() bool {
2495
+	_, ok := v.data.(float64)
2496
+	return ok
2497
+}
2498
+
2499
+// IsFloat64Slice gets whether the object contained is a []float64 or not.
2500
+func (v *Value) IsFloat64Slice() bool {
2501
+	_, ok := v.data.([]float64)
2502
+	return ok
2503
+}
2504
+
2505
+// EachFloat64 calls the specified callback for each object
2506
+// in the []float64.
2507
+//
2508
+// Panics if the object is the wrong type.
2509
+func (v *Value) EachFloat64(callback func(int, float64) bool) *Value {
2510
+
2511
+	for index, val := range v.MustFloat64Slice() {
2512
+		carryon := callback(index, val)
2513
+		if carryon == false {
2514
+			break
2515
+		}
2516
+	}
2517
+
2518
+	return v
2519
+
2520
+}
2521
+
2522
+// WhereFloat64 uses the specified decider function to select items
2523
+// from the []float64.  The object contained in the result will contain
2524
+// only the selected items.
2525
+func (v *Value) WhereFloat64(decider func(int, float64) bool) *Value {
2526
+
2527
+	var selected []float64
2528
+
2529
+	v.EachFloat64(func(index int, val float64) bool {
2530
+		shouldSelect := decider(index, val)
2531
+		if shouldSelect == false {
2532
+			selected = append(selected, val)
2533
+		}
2534
+		return true
2535
+	})
2536
+
2537
+	return &Value{data: selected}
2538
+
2539
+}
2540
+
2541
+// GroupFloat64 uses the specified grouper function to group the items
2542
+// keyed by the return of the grouper.  The object contained in the
2543
+// result will contain a map[string][]float64.
2544
+func (v *Value) GroupFloat64(grouper func(int, float64) string) *Value {
2545
+
2546
+	groups := make(map[string][]float64)
2547
+
2548
+	v.EachFloat64(func(index int, val float64) bool {
2549
+		group := grouper(index, val)
2550
+		if _, ok := groups[group]; !ok {
2551
+			groups[group] = make([]float64, 0)
2552
+		}
2553
+		groups[group] = append(groups[group], val)
2554
+		return true
2555
+	})
2556
+
2557
+	return &Value{data: groups}
2558
+
2559
+}
2560
+
2561
+// ReplaceFloat64 uses the specified function to replace each float64s
2562
+// by iterating each item.  The data in the returned result will be a
2563
+// []float64 containing the replaced items.
2564
+func (v *Value) ReplaceFloat64(replacer func(int, float64) float64) *Value {
2565
+
2566
+	arr := v.MustFloat64Slice()
2567
+	replaced := make([]float64, len(arr))
2568
+
2569
+	v.EachFloat64(func(index int, val float64) bool {
2570
+		replaced[index] = replacer(index, val)
2571
+		return true
2572
+	})
2573
+
2574
+	return &Value{data: replaced}
2575
+
2576
+}
2577
+
2578
+// CollectFloat64 uses the specified collector function to collect a value
2579
+// for each of the float64s in the slice.  The data returned will be a
2580
+// []interface{}.
2581
+func (v *Value) CollectFloat64(collector func(int, float64) interface{}) *Value {
2582
+
2583
+	arr := v.MustFloat64Slice()
2584
+	collected := make([]interface{}, len(arr))
2585
+
2586
+	v.EachFloat64(func(index int, val float64) bool {
2587
+		collected[index] = collector(index, val)
2588
+		return true
2589
+	})
2590
+
2591
+	return &Value{data: collected}
2592
+}
2593
+
2594
+/*
2595
+	Complex64 (complex64 and []complex64)
2596
+	--------------------------------------------------
2597
+*/
2598
+
2599
+// Complex64 gets the value as a complex64, returns the optionalDefault
2600
+// value or a system default object if the value is the wrong type.
2601
+func (v *Value) Complex64(optionalDefault ...complex64) complex64 {
2602
+	if s, ok := v.data.(complex64); ok {
2603
+		return s
2604
+	}
2605
+	if len(optionalDefault) == 1 {
2606
+		return optionalDefault[0]
2607
+	}
2608
+	return 0
2609
+}
2610
+
2611
+// MustComplex64 gets the value as a complex64.
2612
+//
2613
+// Panics if the object is not a complex64.
2614
+func (v *Value) MustComplex64() complex64 {
2615
+	return v.data.(complex64)
2616
+}
2617
+
2618
+// Complex64Slice gets the value as a []complex64, returns the optionalDefault
2619
+// value or nil if the value is not a []complex64.
2620
+func (v *Value) Complex64Slice(optionalDefault ...[]complex64) []complex64 {
2621
+	if s, ok := v.data.([]complex64); ok {
2622
+		return s
2623
+	}
2624
+	if len(optionalDefault) == 1 {
2625
+		return optionalDefault[0]
2626
+	}
2627
+	return nil
2628
+}
2629
+
2630
+// MustComplex64Slice gets the value as a []complex64.
2631
+//
2632
+// Panics if the object is not a []complex64.
2633
+func (v *Value) MustComplex64Slice() []complex64 {
2634
+	return v.data.([]complex64)
2635
+}
2636
+
2637
+// IsComplex64 gets whether the object contained is a complex64 or not.
2638
+func (v *Value) IsComplex64() bool {
2639
+	_, ok := v.data.(complex64)
2640
+	return ok
2641
+}
2642
+
2643
+// IsComplex64Slice gets whether the object contained is a []complex64 or not.
2644
+func (v *Value) IsComplex64Slice() bool {
2645
+	_, ok := v.data.([]complex64)
2646
+	return ok
2647
+}
2648
+
2649
+// EachComplex64 calls the specified callback for each object
2650
+// in the []complex64.
2651
+//
2652
+// Panics if the object is the wrong type.
2653
+func (v *Value) EachComplex64(callback func(int, complex64) bool) *Value {
2654
+
2655
+	for index, val := range v.MustComplex64Slice() {
2656
+		carryon := callback(index, val)
2657
+		if carryon == false {
2658
+			break
2659
+		}
2660
+	}
2661
+
2662
+	return v
2663
+
2664
+}
2665
+
2666
+// WhereComplex64 uses the specified decider function to select items
2667
+// from the []complex64.  The object contained in the result will contain
2668
+// only the selected items.
2669
+func (v *Value) WhereComplex64(decider func(int, complex64) bool) *Value {
2670
+
2671
+	var selected []complex64
2672
+
2673
+	v.EachComplex64(func(index int, val complex64) bool {
2674
+		shouldSelect := decider(index, val)
2675
+		if shouldSelect == false {
2676
+			selected = append(selected, val)
2677
+		}
2678
+		return true
2679
+	})
2680
+
2681
+	return &Value{data: selected}
2682
+
2683
+}
2684
+
2685
+// GroupComplex64 uses the specified grouper function to group the items
2686
+// keyed by the return of the grouper.  The object contained in the
2687
+// result will contain a map[string][]complex64.
2688
+func (v *Value) GroupComplex64(grouper func(int, complex64) string) *Value {
2689
+
2690
+	groups := make(map[string][]complex64)
2691
+
2692
+	v.EachComplex64(func(index int, val complex64) bool {
2693
+		group := grouper(index, val)
2694
+		if _, ok := groups[group]; !ok {
2695
+			groups[group] = make([]complex64, 0)
2696
+		}
2697
+		groups[group] = append(groups[group], val)
2698
+		return true
2699
+	})
2700
+
2701
+	return &Value{data: groups}
2702
+
2703
+}
2704
+
2705
+// ReplaceComplex64 uses the specified function to replace each complex64s
2706
+// by iterating each item.  The data in the returned result will be a
2707
+// []complex64 containing the replaced items.
2708
+func (v *Value) ReplaceComplex64(replacer func(int, complex64) complex64) *Value {
2709
+
2710
+	arr := v.MustComplex64Slice()
2711
+	replaced := make([]complex64, len(arr))
2712
+
2713
+	v.EachComplex64(func(index int, val complex64) bool {
2714
+		replaced[index] = replacer(index, val)
2715
+		return true
2716
+	})
2717
+
2718
+	return &Value{data: replaced}
2719
+
2720
+}
2721
+
2722
+// CollectComplex64 uses the specified collector function to collect a value
2723
+// for each of the complex64s in the slice.  The data returned will be a
2724
+// []interface{}.
2725
+func (v *Value) CollectComplex64(collector func(int, complex64) interface{}) *Value {
2726
+
2727
+	arr := v.MustComplex64Slice()
2728
+	collected := make([]interface{}, len(arr))
2729
+
2730
+	v.EachComplex64(func(index int, val complex64) bool {
2731
+		collected[index] = collector(index, val)
2732
+		return true
2733
+	})
2734
+
2735
+	return &Value{data: collected}
2736
+}
2737
+
2738
+/*
2739
+	Complex128 (complex128 and []complex128)
2740
+	--------------------------------------------------
2741
+*/
2742
+
2743
+// Complex128 gets the value as a complex128, returns the optionalDefault
2744
+// value or a system default object if the value is the wrong type.
2745
+func (v *Value) Complex128(optionalDefault ...complex128) complex128 {
2746
+	if s, ok := v.data.(complex128); ok {
2747
+		return s
2748
+	}
2749
+	if len(optionalDefault) == 1 {
2750
+		return optionalDefault[0]
2751
+	}
2752
+	return 0
2753
+}
2754
+
2755
+// MustComplex128 gets the value as a complex128.
2756
+//
2757
+// Panics if the object is not a complex128.
2758
+func (v *Value) MustComplex128() complex128 {
2759
+	return v.data.(complex128)
2760
+}
2761
+
2762
+// Complex128Slice gets the value as a []complex128, returns the optionalDefault
2763
+// value or nil if the value is not a []complex128.
2764
+func (v *Value) Complex128Slice(optionalDefault ...[]complex128) []complex128 {
2765
+	if s, ok := v.data.([]complex128); ok {
2766
+		return s
2767
+	}
2768
+	if len(optionalDefault) == 1 {
2769
+		return optionalDefault[0]
2770
+	}
2771
+	return nil
2772
+}
2773
+
2774
+// MustComplex128Slice gets the value as a []complex128.
2775
+//
2776
+// Panics if the object is not a []complex128.
2777
+func (v *Value) MustComplex128Slice() []complex128 {
2778
+	return v.data.([]complex128)
2779
+}
2780
+
2781
+// IsComplex128 gets whether the object contained is a complex128 or not.
2782
+func (v *Value) IsComplex128() bool {
2783
+	_, ok := v.data.(complex128)
2784
+	return ok
2785
+}
2786
+
2787
+// IsComplex128Slice gets whether the object contained is a []complex128 or not.
2788
+func (v *Value) IsComplex128Slice() bool {
2789
+	_, ok := v.data.([]complex128)
2790
+	return ok
2791
+}
2792
+
2793
+// EachComplex128 calls the specified callback for each object
2794
+// in the []complex128.
2795
+//
2796
+// Panics if the object is the wrong type.
2797
+func (v *Value) EachComplex128(callback func(int, complex128) bool) *Value {
2798
+
2799
+	for index, val := range v.MustComplex128Slice() {
2800
+		carryon := callback(index, val)
2801
+		if carryon == false {
2802
+			break
2803
+		}
2804
+	}
2805
+
2806
+	return v
2807
+
2808
+}
2809
+
2810
+// WhereComplex128 uses the specified decider function to select items
2811
+// from the []complex128.  The object contained in the result will contain
2812
+// only the selected items.
2813
+func (v *Value) WhereComplex128(decider func(int, complex128) bool) *Value {
2814
+
2815
+	var selected []complex128
2816
+
2817
+	v.EachComplex128(func(index int, val complex128) bool {
2818
+		shouldSelect := decider(index, val)
2819
+		if shouldSelect == false {
2820
+			selected = append(selected, val)
2821
+		}
2822
+		return true
2823
+	})
2824
+
2825
+	return &Value{data: selected}
2826
+
2827
+}
2828
+
2829
+// GroupComplex128 uses the specified grouper function to group the items
2830
+// keyed by the return of the grouper.  The object contained in the
2831
+// result will contain a map[string][]complex128.
2832
+func (v *Value) GroupComplex128(grouper func(int, complex128) string) *Value {
2833
+
2834
+	groups := make(map[string][]complex128)
2835
+
2836
+	v.EachComplex128(func(index int, val complex128) bool {
2837
+		group := grouper(index, val)
2838
+		if _, ok := groups[group]; !ok {
2839
+			groups[group] = make([]complex128, 0)
2840
+		}
2841
+		groups[group] = append(groups[group], val)
2842
+		return true
2843
+	})
2844
+
2845
+	return &Value{data: groups}
2846
+
2847
+}
2848
+
2849
+// ReplaceComplex128 uses the specified function to replace each complex128s
2850
+// by iterating each item.  The data in the returned result will be a
2851
+// []complex128 containing the replaced items.
2852
+func (v *Value) ReplaceComplex128(replacer func(int, complex128) complex128) *Value {
2853
+
2854
+	arr := v.MustComplex128Slice()
2855
+	replaced := make([]complex128, len(arr))
2856
+
2857
+	v.EachComplex128(func(index int, val complex128) bool {
2858
+		replaced[index] = replacer(index, val)
2859
+		return true
2860
+	})
2861
+
2862
+	return &Value{data: replaced}
2863
+
2864
+}
2865
+
2866
+// CollectComplex128 uses the specified collector function to collect a value
2867
+// for each of the complex128s in the slice.  The data returned will be a
2868
+// []interface{}.
2869
+func (v *Value) CollectComplex128(collector func(int, complex128) interface{}) *Value {
2870
+
2871
+	arr := v.MustComplex128Slice()
2872
+	collected := make([]interface{}, len(arr))
2873
+
2874
+	v.EachComplex128(func(index int, val complex128) bool {
2875
+		collected[index] = collector(index, val)
2876
+		return true
2877
+	})
2878
+
2879
+	return &Value{data: collected}
2880
+}
0 2881
new file mode 100644
... ...
@@ -0,0 +1,13 @@
0
+package objx
1
+
2
+// Value provides methods for extracting interface{} data in various
3
+// types.
4
+type Value struct {
5
+	// data contains the raw data being managed by this Value
6
+	data interface{}
7
+}
8
+
9
+// Data returns the raw data contained by this Value
10
+func (v *Value) Data() interface{} {
11
+	return v.data
12
+}
0 13
new file mode 100644
... ...
@@ -0,0 +1,911 @@
0
+package assert
1
+
2
+import (
3
+	"bufio"
4
+	"bytes"
5
+	"fmt"
6
+	"math"
7
+	"reflect"
8
+	"regexp"
9
+	"runtime"
10
+	"strings"
11
+	"time"
12
+	"unicode"
13
+	"unicode/utf8"
14
+)
15
+
16
+// TestingT is an interface wrapper around *testing.T
17
+type TestingT interface {
18
+	Errorf(format string, args ...interface{})
19
+}
20
+
21
+// Comparison a custom function that returns true on success and false on failure
22
+type Comparison func() (success bool)
23
+
24
+/*
25
+	Helper functions
26
+*/
27
+
28
+// ObjectsAreEqual determines if two objects are considered equal.
29
+//
30
+// This function does no assertion of any kind.
31
+func ObjectsAreEqual(expected, actual interface{}) bool {
32
+
33
+	if expected == nil || actual == nil {
34
+		return expected == actual
35
+	}
36
+
37
+	if reflect.DeepEqual(expected, actual) {
38
+		return true
39
+	}
40
+
41
+	return false
42
+
43
+}
44
+
45
+// ObjectsAreEqualValues gets whether two objects are equal, or if their
46
+// values are equal.
47
+func ObjectsAreEqualValues(expected, actual interface{}) bool {
48
+	if ObjectsAreEqual(expected, actual) {
49
+		return true
50
+	}
51
+
52
+	actualType := reflect.TypeOf(actual)
53
+	expectedValue := reflect.ValueOf(expected)
54
+	if expectedValue.Type().ConvertibleTo(actualType) {
55
+		// Attempt comparison after type conversion
56
+		if reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), actual) {
57
+			return true
58
+		}
59
+	}
60
+
61
+	return false
62
+}
63
+
64
+/* CallerInfo is necessary because the assert functions use the testing object
65
+internally, causing it to print the file:line of the assert method, rather than where
66
+the problem actually occured in calling code.*/
67
+
68
+// CallerInfo returns an array of strings containing the file and line number
69
+// of each stack frame leading from the current test to the assert call that
70
+// failed.
71
+func CallerInfo() []string {
72
+
73
+	pc := uintptr(0)
74
+	file := ""
75
+	line := 0
76
+	ok := false
77
+	name := ""
78
+
79
+	callers := []string{}
80
+	for i := 0; ; i++ {
81
+		pc, file, line, ok = runtime.Caller(i)
82
+		if !ok {
83
+			return nil
84
+		}
85
+
86
+		// This is a huge edge case, but it will panic if this is the case, see #180
87
+		if file == "<autogenerated>" {
88
+			break
89
+		}
90
+
91
+		parts := strings.Split(file, "/")
92
+		dir := parts[len(parts)-2]
93
+		file = parts[len(parts)-1]
94
+		if (dir != "assert" && dir != "mock" && dir != "require") || file == "mock_test.go" {
95
+			callers = append(callers, fmt.Sprintf("%s:%d", file, line))
96
+		}
97
+
98
+		f := runtime.FuncForPC(pc)
99
+		if f == nil {
100
+			break
101
+		}
102
+		name = f.Name()
103
+		// Drop the package
104
+		segments := strings.Split(name, ".")
105
+		name = segments[len(segments)-1]
106
+		if isTest(name, "Test") ||
107
+			isTest(name, "Benchmark") ||
108
+			isTest(name, "Example") {
109
+			break
110
+		}
111
+	}
112
+
113
+	return callers
114
+}
115
+
116
+// Stolen from the `go test` tool.
117
+// isTest tells whether name looks like a test (or benchmark, according to prefix).
118
+// It is a Test (say) if there is a character after Test that is not a lower-case letter.
119
+// We don't want TesticularCancer.
120
+func isTest(name, prefix string) bool {
121
+	if !strings.HasPrefix(name, prefix) {
122
+		return false
123
+	}
124
+	if len(name) == len(prefix) { // "Test" is ok
125
+		return true
126
+	}
127
+	rune, _ := utf8.DecodeRuneInString(name[len(prefix):])
128
+	return !unicode.IsLower(rune)
129
+}
130
+
131
+// getWhitespaceString returns a string that is long enough to overwrite the default
132
+// output from the go testing framework.
133
+func getWhitespaceString() string {
134
+
135
+	_, file, line, ok := runtime.Caller(1)
136
+	if !ok {
137
+		return ""
138
+	}
139
+	parts := strings.Split(file, "/")
140
+	file = parts[len(parts)-1]
141
+
142
+	return strings.Repeat(" ", len(fmt.Sprintf("%s:%d:      ", file, line)))
143
+
144
+}
145
+
146
+func messageFromMsgAndArgs(msgAndArgs ...interface{}) string {
147
+	if len(msgAndArgs) == 0 || msgAndArgs == nil {
148
+		return ""
149
+	}
150
+	if len(msgAndArgs) == 1 {
151
+		return msgAndArgs[0].(string)
152
+	}
153
+	if len(msgAndArgs) > 1 {
154
+		return fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...)
155
+	}
156
+	return ""
157
+}
158
+
159
+// Indents all lines of the message by appending a number of tabs to each line, in an output format compatible with Go's
160
+// test printing (see inner comment for specifics)
161
+func indentMessageLines(message string, tabs int) string {
162
+	outBuf := new(bytes.Buffer)
163
+
164
+	for i, scanner := 0, bufio.NewScanner(strings.NewReader(message)); scanner.Scan(); i++ {
165
+		if i != 0 {
166
+			outBuf.WriteRune('\n')
167
+		}
168
+		for ii := 0; ii < tabs; ii++ {
169
+			outBuf.WriteRune('\t')
170
+			// Bizarrely, all lines except the first need one fewer tabs prepended, so deliberately advance the counter
171
+			// by 1 prematurely.
172
+			if ii == 0 && i > 0 {
173
+				ii++
174
+			}
175
+		}
176
+		outBuf.WriteString(scanner.Text())
177
+	}
178
+
179
+	return outBuf.String()
180
+}
181
+
182
+// Fail reports a failure through
183
+func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool {
184
+
185
+	message := messageFromMsgAndArgs(msgAndArgs...)
186
+
187
+	errorTrace := strings.Join(CallerInfo(), "\n\r\t\t\t")
188
+	if len(message) > 0 {
189
+		t.Errorf("\r%s\r\tError Trace:\t%s\n"+
190
+			"\r\tError:%s\n"+
191
+			"\r\tMessages:\t%s\n\r",
192
+			getWhitespaceString(),
193
+			errorTrace,
194
+			indentMessageLines(failureMessage, 2),
195
+			message)
196
+	} else {
197
+		t.Errorf("\r%s\r\tError Trace:\t%s\n"+
198
+			"\r\tError:%s\n\r",
199
+			getWhitespaceString(),
200
+			errorTrace,
201
+			indentMessageLines(failureMessage, 2))
202
+	}
203
+
204
+	return false
205
+}
206
+
207
+// Implements asserts that an object is implemented by the specified interface.
208
+//
209
+//    assert.Implements(t, (*MyInterface)(nil), new(MyObject), "MyObject")
210
+func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {
211
+
212
+	interfaceType := reflect.TypeOf(interfaceObject).Elem()
213
+
214
+	if !reflect.TypeOf(object).Implements(interfaceType) {
215
+		return Fail(t, fmt.Sprintf("Object must implement %v", interfaceType), msgAndArgs...)
216
+	}
217
+
218
+	return true
219
+
220
+}
221
+
222
+// IsType asserts that the specified objects are of the same type.
223
+func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool {
224
+
225
+	if !ObjectsAreEqual(reflect.TypeOf(object), reflect.TypeOf(expectedType)) {
226
+		return Fail(t, fmt.Sprintf("Object expected to be of type %v, but was %v", reflect.TypeOf(expectedType), reflect.TypeOf(object)), msgAndArgs...)
227
+	}
228
+
229
+	return true
230
+}
231
+
232
+// Equal asserts that two objects are equal.
233
+//
234
+//    assert.Equal(t, 123, 123, "123 and 123 should be equal")
235
+//
236
+// Returns whether the assertion was successful (true) or not (false).
237
+func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
238
+
239
+	if !ObjectsAreEqual(expected, actual) {
240
+		return Fail(t, fmt.Sprintf("Not equal: %#v (expected)\n"+
241
+			"        != %#v (actual)", expected, actual), msgAndArgs...)
242
+	}
243
+
244
+	return true
245
+
246
+}
247
+
248
+// EqualValues asserts that two objects are equal or convertable to the same types
249
+// and equal.
250
+//
251
+//    assert.EqualValues(t, uint32(123), int32(123), "123 and 123 should be equal")
252
+//
253
+// Returns whether the assertion was successful (true) or not (false).
254
+func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
255
+
256
+	if !ObjectsAreEqualValues(expected, actual) {
257
+		return Fail(t, fmt.Sprintf("Not equal: %#v (expected)\n"+
258
+			"        != %#v (actual)", expected, actual), msgAndArgs...)
259
+	}
260
+
261
+	return true
262
+
263
+}
264
+
265
+// Exactly asserts that two objects are equal is value and type.
266
+//
267
+//    assert.Exactly(t, int32(123), int64(123), "123 and 123 should NOT be equal")
268
+//
269
+// Returns whether the assertion was successful (true) or not (false).
270
+func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
271
+
272
+	aType := reflect.TypeOf(expected)
273
+	bType := reflect.TypeOf(actual)
274
+
275
+	if aType != bType {
276
+		return Fail(t, "Types expected to match exactly", "%v != %v", aType, bType)
277
+	}
278
+
279
+	return Equal(t, expected, actual, msgAndArgs...)
280
+
281
+}
282
+
283
+// NotNil asserts that the specified object is not nil.
284
+//
285
+//    assert.NotNil(t, err, "err should be something")
286
+//
287
+// Returns whether the assertion was successful (true) or not (false).
288
+func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
289
+
290
+	success := true
291
+
292
+	if object == nil {
293
+		success = false
294
+	} else {
295
+		value := reflect.ValueOf(object)
296
+		kind := value.Kind()
297
+		if kind >= reflect.Chan && kind <= reflect.Slice && value.IsNil() {
298
+			success = false
299
+		}
300
+	}
301
+
302
+	if !success {
303
+		Fail(t, "Expected value not to be nil.", msgAndArgs...)
304
+	}
305
+
306
+	return success
307
+}
308
+
309
+// isNil checks if a specified object is nil or not, without Failing.
310
+func isNil(object interface{}) bool {
311
+	if object == nil {
312
+		return true
313
+	}
314
+
315
+	value := reflect.ValueOf(object)
316
+	kind := value.Kind()
317
+	if kind >= reflect.Chan && kind <= reflect.Slice && value.IsNil() {
318
+		return true
319
+	}
320
+
321
+	return false
322
+}
323
+
324
+// Nil asserts that the specified object is nil.
325
+//
326
+//    assert.Nil(t, err, "err should be nothing")
327
+//
328
+// Returns whether the assertion was successful (true) or not (false).
329
+func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
330
+	if isNil(object) {
331
+		return true
332
+	}
333
+	return Fail(t, fmt.Sprintf("Expected nil, but got: %#v", object), msgAndArgs...)
334
+}
335
+
336
+var numericZeros = []interface{}{
337
+	int(0),
338
+	int8(0),
339
+	int16(0),
340
+	int32(0),
341
+	int64(0),
342
+	uint(0),
343
+	uint8(0),
344
+	uint16(0),
345
+	uint32(0),
346
+	uint64(0),
347
+	float32(0),
348
+	float64(0),
349
+}
350
+
351
+// isEmpty gets whether the specified object is considered empty or not.
352
+func isEmpty(object interface{}) bool {
353
+
354
+	if object == nil {
355
+		return true
356
+	} else if object == "" {
357
+		return true
358
+	} else if object == false {
359
+		return true
360
+	}
361
+
362
+	for _, v := range numericZeros {
363
+		if object == v {
364
+			return true
365
+		}
366
+	}
367
+
368
+	objValue := reflect.ValueOf(object)
369
+
370
+	switch objValue.Kind() {
371
+	case reflect.Map:
372
+		fallthrough
373
+	case reflect.Slice, reflect.Chan:
374
+		{
375
+			return (objValue.Len() == 0)
376
+		}
377
+	case reflect.Ptr:
378
+		{
379
+			switch object.(type) {
380
+			case *time.Time:
381
+				return object.(*time.Time).IsZero()
382
+			default:
383
+				return false
384
+			}
385
+		}
386
+	}
387
+	return false
388
+}
389
+
390
+// Empty asserts that the specified object is empty.  I.e. nil, "", false, 0 or either
391
+// a slice or a channel with len == 0.
392
+//
393
+// assert.Empty(t, obj)
394
+//
395
+// Returns whether the assertion was successful (true) or not (false).
396
+func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
397
+
398
+	pass := isEmpty(object)
399
+	if !pass {
400
+		Fail(t, fmt.Sprintf("Should be empty, but was %v", object), msgAndArgs...)
401
+	}
402
+
403
+	return pass
404
+
405
+}
406
+
407
+// NotEmpty asserts that the specified object is NOT empty.  I.e. not nil, "", false, 0 or either
408
+// a slice or a channel with len == 0.
409
+//
410
+// if assert.NotEmpty(t, obj) {
411
+//   assert.Equal(t, "two", obj[1])
412
+// }
413
+//
414
+// Returns whether the assertion was successful (true) or not (false).
415
+func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
416
+
417
+	pass := !isEmpty(object)
418
+	if !pass {
419
+		Fail(t, fmt.Sprintf("Should NOT be empty, but was %v", object), msgAndArgs...)
420
+	}
421
+
422
+	return pass
423
+
424
+}
425
+
426
+// getLen try to get length of object.
427
+// return (false, 0) if impossible.
428
+func getLen(x interface{}) (ok bool, length int) {
429
+	v := reflect.ValueOf(x)
430
+	defer func() {
431
+		if e := recover(); e != nil {
432
+			ok = false
433
+		}
434
+	}()
435
+	return true, v.Len()
436
+}
437
+
438
+// Len asserts that the specified object has specific length.
439
+// Len also fails if the object has a type that len() not accept.
440
+//
441
+//    assert.Len(t, mySlice, 3, "The size of slice is not 3")
442
+//
443
+// Returns whether the assertion was successful (true) or not (false).
444
+func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) bool {
445
+	ok, l := getLen(object)
446
+	if !ok {
447
+		return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", object), msgAndArgs...)
448
+	}
449
+
450
+	if l != length {
451
+		return Fail(t, fmt.Sprintf("\"%s\" should have %d item(s), but has %d", object, length, l), msgAndArgs...)
452
+	}
453
+	return true
454
+}
455
+
456
+// True asserts that the specified value is true.
457
+//
458
+//    assert.True(t, myBool, "myBool should be true")
459
+//
460
+// Returns whether the assertion was successful (true) or not (false).
461
+func True(t TestingT, value bool, msgAndArgs ...interface{}) bool {
462
+
463
+	if value != true {
464
+		return Fail(t, "Should be true", msgAndArgs...)
465
+	}
466
+
467
+	return true
468
+
469
+}
470
+
471
+// False asserts that the specified value is true.
472
+//
473
+//    assert.False(t, myBool, "myBool should be false")
474
+//
475
+// Returns whether the assertion was successful (true) or not (false).
476
+func False(t TestingT, value bool, msgAndArgs ...interface{}) bool {
477
+
478
+	if value != false {
479
+		return Fail(t, "Should be false", msgAndArgs...)
480
+	}
481
+
482
+	return true
483
+
484
+}
485
+
486
+// NotEqual asserts that the specified values are NOT equal.
487
+//
488
+//    assert.NotEqual(t, obj1, obj2, "two objects shouldn't be equal")
489
+//
490
+// Returns whether the assertion was successful (true) or not (false).
491
+func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
492
+
493
+	if ObjectsAreEqual(expected, actual) {
494
+		return Fail(t, fmt.Sprintf("Should not be: %#v\n", actual), msgAndArgs...)
495
+	}
496
+
497
+	return true
498
+
499
+}
500
+
501
+// containsElement try loop over the list check if the list includes the element.
502
+// return (false, false) if impossible.
503
+// return (true, false) if element was not found.
504
+// return (true, true) if element was found.
505
+func includeElement(list interface{}, element interface{}) (ok, found bool) {
506
+
507
+	listValue := reflect.ValueOf(list)
508
+	elementValue := reflect.ValueOf(element)
509
+	defer func() {
510
+		if e := recover(); e != nil {
511
+			ok = false
512
+			found = false
513
+		}
514
+	}()
515
+
516
+	if reflect.TypeOf(list).Kind() == reflect.String {
517
+		return true, strings.Contains(listValue.String(), elementValue.String())
518
+	}
519
+
520
+	for i := 0; i < listValue.Len(); i++ {
521
+		if ObjectsAreEqual(listValue.Index(i).Interface(), element) {
522
+			return true, true
523
+		}
524
+	}
525
+	return true, false
526
+
527
+}
528
+
529
+// Contains asserts that the specified string or list(array, slice...) contains the
530
+// specified substring or element.
531
+//
532
+//    assert.Contains(t, "Hello World", "World", "But 'Hello World' does contain 'World'")
533
+//    assert.Contains(t, ["Hello", "World"], "World", "But ["Hello", "World"] does contain 'World'")
534
+//
535
+// Returns whether the assertion was successful (true) or not (false).
536
+func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool {
537
+
538
+	ok, found := includeElement(s, contains)
539
+	if !ok {
540
+		return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", s), msgAndArgs...)
541
+	}
542
+	if !found {
543
+		return Fail(t, fmt.Sprintf("\"%s\" does not contain \"%s\"", s, contains), msgAndArgs...)
544
+	}
545
+
546
+	return true
547
+
548
+}
549
+
550
+// NotContains asserts that the specified string or list(array, slice...) does NOT contain the
551
+// specified substring or element.
552
+//
553
+//    assert.NotContains(t, "Hello World", "Earth", "But 'Hello World' does NOT contain 'Earth'")
554
+//    assert.NotContains(t, ["Hello", "World"], "Earth", "But ['Hello', 'World'] does NOT contain 'Earth'")
555
+//
556
+// Returns whether the assertion was successful (true) or not (false).
557
+func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool {
558
+
559
+	ok, found := includeElement(s, contains)
560
+	if !ok {
561
+		return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", s), msgAndArgs...)
562
+	}
563
+	if found {
564
+		return Fail(t, fmt.Sprintf("\"%s\" should not contain \"%s\"", s, contains), msgAndArgs...)
565
+	}
566
+
567
+	return true
568
+
569
+}
570
+
571
+// Condition uses a Comparison to assert a complex condition.
572
+func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) bool {
573
+	result := comp()
574
+	if !result {
575
+		Fail(t, "Condition failed!", msgAndArgs...)
576
+	}
577
+	return result
578
+}
579
+
580
+// PanicTestFunc defines a func that should be passed to the assert.Panics and assert.NotPanics
581
+// methods, and represents a simple func that takes no arguments, and returns nothing.
582
+type PanicTestFunc func()
583
+
584
+// didPanic returns true if the function passed to it panics. Otherwise, it returns false.
585
+func didPanic(f PanicTestFunc) (bool, interface{}) {
586
+
587
+	didPanic := false
588
+	var message interface{}
589
+	func() {
590
+
591
+		defer func() {
592
+			if message = recover(); message != nil {
593
+				didPanic = true
594
+			}
595
+		}()
596
+
597
+		// call the target function
598
+		f()
599
+
600
+	}()
601
+
602
+	return didPanic, message
603
+
604
+}
605
+
606
+// Panics asserts that the code inside the specified PanicTestFunc panics.
607
+//
608
+//   assert.Panics(t, func(){
609
+//     GoCrazy()
610
+//   }, "Calling GoCrazy() should panic")
611
+//
612
+// Returns whether the assertion was successful (true) or not (false).
613
+func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {
614
+
615
+	if funcDidPanic, panicValue := didPanic(f); !funcDidPanic {
616
+		return Fail(t, fmt.Sprintf("func %#v should panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...)
617
+	}
618
+
619
+	return true
620
+}
621
+
622
+// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic.
623
+//
624
+//   assert.NotPanics(t, func(){
625
+//     RemainCalm()
626
+//   }, "Calling RemainCalm() should NOT panic")
627
+//
628
+// Returns whether the assertion was successful (true) or not (false).
629
+func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {
630
+
631
+	if funcDidPanic, panicValue := didPanic(f); funcDidPanic {
632
+		return Fail(t, fmt.Sprintf("func %#v should not panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...)
633
+	}
634
+
635
+	return true
636
+}
637
+
638
+// WithinDuration asserts that the two times are within duration delta of each other.
639
+//
640
+//   assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second, "The difference should not be more than 10s")
641
+//
642
+// Returns whether the assertion was successful (true) or not (false).
643
+func WithinDuration(t TestingT, expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool {
644
+
645
+	dt := expected.Sub(actual)
646
+	if dt < -delta || dt > delta {
647
+		return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...)
648
+	}
649
+
650
+	return true
651
+}
652
+
653
+func toFloat(x interface{}) (float64, bool) {
654
+	var xf float64
655
+	xok := true
656
+
657
+	switch xn := x.(type) {
658
+	case uint8:
659
+		xf = float64(xn)
660
+	case uint16:
661
+		xf = float64(xn)
662
+	case uint32:
663
+		xf = float64(xn)
664
+	case uint64:
665
+		xf = float64(xn)
666
+	case int:
667
+		xf = float64(xn)
668
+	case int8:
669
+		xf = float64(xn)
670
+	case int16:
671
+		xf = float64(xn)
672
+	case int32:
673
+		xf = float64(xn)
674
+	case int64:
675
+		xf = float64(xn)
676
+	case float32:
677
+		xf = float64(xn)
678
+	case float64:
679
+		xf = float64(xn)
680
+	default:
681
+		xok = false
682
+	}
683
+
684
+	return xf, xok
685
+}
686
+
687
+// InDelta asserts that the two numerals are within delta of each other.
688
+//
689
+// 	 assert.InDelta(t, math.Pi, (22 / 7.0), 0.01)
690
+//
691
+// Returns whether the assertion was successful (true) or not (false).
692
+func InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
693
+
694
+	af, aok := toFloat(expected)
695
+	bf, bok := toFloat(actual)
696
+
697
+	if !aok || !bok {
698
+		return Fail(t, fmt.Sprintf("Parameters must be numerical"), msgAndArgs...)
699
+	}
700
+
701
+	if math.IsNaN(af) {
702
+		return Fail(t, fmt.Sprintf("Actual must not be NaN"), msgAndArgs...)
703
+	}
704
+
705
+	if math.IsNaN(bf) {
706
+		return Fail(t, fmt.Sprintf("Expected %v with delta %v, but was NaN", expected, delta), msgAndArgs...)
707
+	}
708
+
709
+	dt := af - bf
710
+	if dt < -delta || dt > delta {
711
+		return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...)
712
+	}
713
+
714
+	return true
715
+}
716
+
717
+// InDeltaSlice is the same as InDelta, except it compares two slices.
718
+func InDeltaSlice(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
719
+	if expected == nil || actual == nil ||
720
+		reflect.TypeOf(actual).Kind() != reflect.Slice ||
721
+		reflect.TypeOf(expected).Kind() != reflect.Slice {
722
+		return Fail(t, fmt.Sprintf("Parameters must be slice"), msgAndArgs...)
723
+	}
724
+
725
+	actualSlice := reflect.ValueOf(actual)
726
+	expectedSlice := reflect.ValueOf(expected)
727
+
728
+	for i := 0; i < actualSlice.Len(); i++ {
729
+		result := InDelta(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), delta)
730
+		if !result {
731
+			return result
732
+		}
733
+	}
734
+
735
+	return true
736
+}
737
+
738
+// min(|expected|, |actual|) * epsilon
739
+func calcEpsilonDelta(expected, actual interface{}, epsilon float64) float64 {
740
+	af, aok := toFloat(expected)
741
+	bf, bok := toFloat(actual)
742
+
743
+	if !aok || !bok {
744
+		// invalid input
745
+		return 0
746
+	}
747
+
748
+	if af < 0 {
749
+		af = -af
750
+	}
751
+	if bf < 0 {
752
+		bf = -bf
753
+	}
754
+	var delta float64
755
+	if af < bf {
756
+		delta = af * epsilon
757
+	} else {
758
+		delta = bf * epsilon
759
+	}
760
+	return delta
761
+}
762
+
763
+// InEpsilon asserts that expected and actual have a relative error less than epsilon
764
+//
765
+// Returns whether the assertion was successful (true) or not (false).
766
+func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
767
+	delta := calcEpsilonDelta(expected, actual, epsilon)
768
+
769
+	return InDelta(t, expected, actual, delta, msgAndArgs...)
770
+}
771
+
772
+// InEpsilonSlice is the same as InEpsilon, except it compares two slices.
773
+func InEpsilonSlice(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
774
+	if expected == nil || actual == nil ||
775
+		reflect.TypeOf(actual).Kind() != reflect.Slice ||
776
+		reflect.TypeOf(expected).Kind() != reflect.Slice {
777
+		return Fail(t, fmt.Sprintf("Parameters must be slice"), msgAndArgs...)
778
+	}
779
+
780
+	actualSlice := reflect.ValueOf(actual)
781
+	expectedSlice := reflect.ValueOf(expected)
782
+
783
+	for i := 0; i < actualSlice.Len(); i++ {
784
+		result := InEpsilon(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), delta)
785
+		if !result {
786
+			return result
787
+		}
788
+	}
789
+
790
+	return true
791
+}
792
+
793
+/*
794
+	Errors
795
+*/
796
+
797
+// NoError asserts that a function returned no error (i.e. `nil`).
798
+//
799
+//   actualObj, err := SomeFunction()
800
+//   if assert.NoError(t, err) {
801
+//	   assert.Equal(t, actualObj, expectedObj)
802
+//   }
803
+//
804
+// Returns whether the assertion was successful (true) or not (false).
805
+func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool {
806
+	if isNil(err) {
807
+		return true
808
+	}
809
+
810
+	return Fail(t, fmt.Sprintf("No error is expected but got %v", err), msgAndArgs...)
811
+}
812
+
813
+// Error asserts that a function returned an error (i.e. not `nil`).
814
+//
815
+//   actualObj, err := SomeFunction()
816
+//   if assert.Error(t, err, "An error was expected") {
817
+//	   assert.Equal(t, err, expectedError)
818
+//   }
819
+//
820
+// Returns whether the assertion was successful (true) or not (false).
821
+func Error(t TestingT, err error, msgAndArgs ...interface{}) bool {
822
+
823
+	message := messageFromMsgAndArgs(msgAndArgs...)
824
+	return NotNil(t, err, "An error is expected but got nil. %s", message)
825
+
826
+}
827
+
828
+// EqualError asserts that a function returned an error (i.e. not `nil`)
829
+// and that it is equal to the provided error.
830
+//
831
+//   actualObj, err := SomeFunction()
832
+//   if assert.Error(t, err, "An error was expected") {
833
+//	   assert.Equal(t, err, expectedError)
834
+//   }
835
+//
836
+// Returns whether the assertion was successful (true) or not (false).
837
+func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) bool {
838
+
839
+	message := messageFromMsgAndArgs(msgAndArgs...)
840
+	if !NotNil(t, theError, "An error is expected but got nil. %s", message) {
841
+		return false
842
+	}
843
+	s := "An error with value \"%s\" is expected but got \"%s\". %s"
844
+	return Equal(t, errString, theError.Error(),
845
+		s, errString, theError.Error(), message)
846
+}
847
+
848
+// matchRegexp return true if a specified regexp matches a string.
849
+func matchRegexp(rx interface{}, str interface{}) bool {
850
+
851
+	var r *regexp.Regexp
852
+	if rr, ok := rx.(*regexp.Regexp); ok {
853
+		r = rr
854
+	} else {
855
+		r = regexp.MustCompile(fmt.Sprint(rx))
856
+	}
857
+
858
+	return (r.FindStringIndex(fmt.Sprint(str)) != nil)
859
+
860
+}
861
+
862
+// Regexp asserts that a specified regexp matches a string.
863
+//
864
+//  assert.Regexp(t, regexp.MustCompile("start"), "it's starting")
865
+//  assert.Regexp(t, "start...$", "it's not starting")
866
+//
867
+// Returns whether the assertion was successful (true) or not (false).
868
+func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
869
+
870
+	match := matchRegexp(rx, str)
871
+
872
+	if !match {
873
+		Fail(t, fmt.Sprintf("Expect \"%v\" to match \"%v\"", str, rx), msgAndArgs...)
874
+	}
875
+
876
+	return match
877
+}
878
+
879
+// NotRegexp asserts that a specified regexp does not match a string.
880
+//
881
+//  assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting")
882
+//  assert.NotRegexp(t, "^start", "it's not starting")
883
+//
884
+// Returns whether the assertion was successful (true) or not (false).
885
+func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
886
+	match := matchRegexp(rx, str)
887
+
888
+	if match {
889
+		Fail(t, fmt.Sprintf("Expect \"%v\" to NOT match \"%v\"", str, rx), msgAndArgs...)
890
+	}
891
+
892
+	return !match
893
+
894
+}
895
+
896
+// Zero asserts that i is the zero value for its type and returns the truth.
897
+func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool {
898
+	if i != nil && !reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) {
899
+		return Fail(t, fmt.Sprintf("Should be zero, but was %v", i), msgAndArgs...)
900
+	}
901
+	return true
902
+}
903
+
904
+// NotZero asserts that i is not the zero value for its type and returns the truth.
905
+func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool {
906
+	if i == nil || reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) {
907
+		return Fail(t, fmt.Sprintf("Should not be zero, but was %v", i), msgAndArgs...)
908
+	}
909
+	return true
910
+}
0 911
new file mode 100644
... ...
@@ -0,0 +1,45 @@
0
+// Package assert provides a set of comprehensive testing tools for use with the normal Go testing system.
1
+//
2
+// Example Usage
3
+//
4
+// The following is a complete example using assert in a standard test function:
5
+//    import (
6
+//      "testing"
7
+//      "github.com/stretchr/testify/assert"
8
+//    )
9
+//
10
+//    func TestSomething(t *testing.T) {
11
+//
12
+//      var a string = "Hello"
13
+//      var b string = "Hello"
14
+//
15
+//      assert.Equal(t, a, b, "The two words should be the same.")
16
+//
17
+//    }
18
+//
19
+// if you assert many times, use the format below:
20
+//
21
+//    import (
22
+//      "testing"
23
+//      "github.com/stretchr/testify/assert"
24
+//    )
25
+//
26
+//    func TestSomething(t *testing.T) {
27
+//      assert := assert.New(t)
28
+//
29
+//      var a string = "Hello"
30
+//      var b string = "Hello"
31
+//
32
+//      assert.Equal(a, b, "The two words should be the same.")
33
+//    }
34
+//
35
+// Assertions
36
+//
37
+// Assertions allow you to easily write test code, and are global funcs in the `assert` package.
38
+// All assertion functions take, as the first argument, the `*testing.T` object provided by the
39
+// testing framework. This allows the assertion funcs to write the failings and other details to
40
+// the correct place.
41
+//
42
+// Every assertion function also takes an optional string message as the final argument,
43
+// allowing custom error messages to be appended to the message the assertion method outputs.
44
+package assert
0 45
new file mode 100644
... ...
@@ -0,0 +1,10 @@
0
+package assert
1
+
2
+import (
3
+	"errors"
4
+)
5
+
6
+// AnError is an error instance useful for testing.  If the code does not care
7
+// about error specifics, and only needs to return the error for example, this
8
+// error should be used to make the test code more readable.
9
+var AnError = errors.New("assert.AnError general error for testing")
0 10
new file mode 100644
... ...
@@ -0,0 +1,275 @@
0
+package assert
1
+
2
+import "time"
3
+
4
+// Assertions provides assertion methods around the
5
+// TestingT interface.
6
+type Assertions struct {
7
+	t TestingT
8
+}
9
+
10
+// New makes a new Assertions object for the specified TestingT.
11
+func New(t TestingT) *Assertions {
12
+	return &Assertions{
13
+		t: t,
14
+	}
15
+}
16
+
17
+// Fail reports a failure through
18
+func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) bool {
19
+	return Fail(a.t, failureMessage, msgAndArgs...)
20
+}
21
+
22
+// Implements asserts that an object is implemented by the specified interface.
23
+//
24
+//    assert.Implements((*MyInterface)(nil), new(MyObject), "MyObject")
25
+func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {
26
+	return Implements(a.t, interfaceObject, object, msgAndArgs...)
27
+}
28
+
29
+// IsType asserts that the specified objects are of the same type.
30
+func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool {
31
+	return IsType(a.t, expectedType, object, msgAndArgs...)
32
+}
33
+
34
+// Equal asserts that two objects are equal.
35
+//
36
+//    assert.Equal(123, 123, "123 and 123 should be equal")
37
+//
38
+// Returns whether the assertion was successful (true) or not (false).
39
+func (a *Assertions) Equal(expected, actual interface{}, msgAndArgs ...interface{}) bool {
40
+	return Equal(a.t, expected, actual, msgAndArgs...)
41
+}
42
+
43
+// EqualValues asserts that two objects are equal or convertable to the same types
44
+// and equal.
45
+//
46
+//    assert.EqualValues(uint32(123), int32(123), "123 and 123 should be equal")
47
+//
48
+// Returns whether the assertion was successful (true) or not (false).
49
+func (a *Assertions) EqualValues(expected, actual interface{}, msgAndArgs ...interface{}) bool {
50
+	return EqualValues(a.t, expected, actual, msgAndArgs...)
51
+}
52
+
53
+// Exactly asserts that two objects are equal is value and type.
54
+//
55
+//    assert.Exactly(int32(123), int64(123), "123 and 123 should NOT be equal")
56
+//
57
+// Returns whether the assertion was successful (true) or not (false).
58
+func (a *Assertions) Exactly(expected, actual interface{}, msgAndArgs ...interface{}) bool {
59
+	return Exactly(a.t, expected, actual, msgAndArgs...)
60
+}
61
+
62
+// NotNil asserts that the specified object is not nil.
63
+//
64
+//    assert.NotNil(err, "err should be something")
65
+//
66
+// Returns whether the assertion was successful (true) or not (false).
67
+func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) bool {
68
+	return NotNil(a.t, object, msgAndArgs...)
69
+}
70
+
71
+// Nil asserts that the specified object is nil.
72
+//
73
+//    assert.Nil(err, "err should be nothing")
74
+//
75
+// Returns whether the assertion was successful (true) or not (false).
76
+func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) bool {
77
+	return Nil(a.t, object, msgAndArgs...)
78
+}
79
+
80
+// Empty asserts that the specified object is empty.  I.e. nil, "", false, 0 or a
81
+// slice with len == 0.
82
+//
83
+// assert.Empty(obj)
84
+//
85
+// Returns whether the assertion was successful (true) or not (false).
86
+func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) bool {
87
+	return Empty(a.t, object, msgAndArgs...)
88
+}
89
+
90
+// NotEmpty asserts that the specified object is NOT empty.  I.e. not nil, "", false, 0 or a
91
+// slice with len == 0.
92
+//
93
+// if assert.NotEmpty(obj) {
94
+//   assert.Equal("two", obj[1])
95
+// }
96
+//
97
+// Returns whether the assertion was successful (true) or not (false).
98
+func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) bool {
99
+	return NotEmpty(a.t, object, msgAndArgs...)
100
+}
101
+
102
+// Len asserts that the specified object has specific length.
103
+// Len also fails if the object has a type that len() not accept.
104
+//
105
+//    assert.Len(mySlice, 3, "The size of slice is not 3")
106
+//
107
+// Returns whether the assertion was successful (true) or not (false).
108
+func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) bool {
109
+	return Len(a.t, object, length, msgAndArgs...)
110
+}
111
+
112
+// True asserts that the specified value is true.
113
+//
114
+//    assert.True(myBool, "myBool should be true")
115
+//
116
+// Returns whether the assertion was successful (true) or not (false).
117
+func (a *Assertions) True(value bool, msgAndArgs ...interface{}) bool {
118
+	return True(a.t, value, msgAndArgs...)
119
+}
120
+
121
+// False asserts that the specified value is true.
122
+//
123
+//    assert.False(myBool, "myBool should be false")
124
+//
125
+// Returns whether the assertion was successful (true) or not (false).
126
+func (a *Assertions) False(value bool, msgAndArgs ...interface{}) bool {
127
+	return False(a.t, value, msgAndArgs...)
128
+}
129
+
130
+// NotEqual asserts that the specified values are NOT equal.
131
+//
132
+//    assert.NotEqual(obj1, obj2, "two objects shouldn't be equal")
133
+//
134
+// Returns whether the assertion was successful (true) or not (false).
135
+func (a *Assertions) NotEqual(expected, actual interface{}, msgAndArgs ...interface{}) bool {
136
+	return NotEqual(a.t, expected, actual, msgAndArgs...)
137
+}
138
+
139
+// Contains asserts that the specified string contains the specified substring.
140
+//
141
+//    assert.Contains("Hello World", "World", "But 'Hello World' does contain 'World'")
142
+//
143
+// Returns whether the assertion was successful (true) or not (false).
144
+func (a *Assertions) Contains(s, contains interface{}, msgAndArgs ...interface{}) bool {
145
+	return Contains(a.t, s, contains, msgAndArgs...)
146
+}
147
+
148
+// NotContains asserts that the specified string does NOT contain the specified substring.
149
+//
150
+//    assert.NotContains("Hello World", "Earth", "But 'Hello World' does NOT contain 'Earth'")
151
+//
152
+// Returns whether the assertion was successful (true) or not (false).
153
+func (a *Assertions) NotContains(s, contains interface{}, msgAndArgs ...interface{}) bool {
154
+	return NotContains(a.t, s, contains, msgAndArgs...)
155
+}
156
+
157
+// Condition uses a Comparison to assert a complex condition.
158
+func (a *Assertions) Condition(comp Comparison, msgAndArgs ...interface{}) bool {
159
+	return Condition(a.t, comp, msgAndArgs...)
160
+}
161
+
162
+// Panics asserts that the code inside the specified PanicTestFunc panics.
163
+//
164
+//   assert.Panics(func(){
165
+//     GoCrazy()
166
+//   }, "Calling GoCrazy() should panic")
167
+//
168
+// Returns whether the assertion was successful (true) or not (false).
169
+func (a *Assertions) Panics(f PanicTestFunc, msgAndArgs ...interface{}) bool {
170
+	return Panics(a.t, f, msgAndArgs...)
171
+}
172
+
173
+// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic.
174
+//
175
+//   assert.NotPanics(func(){
176
+//     RemainCalm()
177
+//   }, "Calling RemainCalm() should NOT panic")
178
+//
179
+// Returns whether the assertion was successful (true) or not (false).
180
+func (a *Assertions) NotPanics(f PanicTestFunc, msgAndArgs ...interface{}) bool {
181
+	return NotPanics(a.t, f, msgAndArgs...)
182
+}
183
+
184
+// WithinDuration asserts that the two times are within duration delta of each other.
185
+//
186
+//   assert.WithinDuration(time.Now(), time.Now(), 10*time.Second, "The difference should not be more than 10s")
187
+//
188
+// Returns whether the assertion was successful (true) or not (false).
189
+func (a *Assertions) WithinDuration(expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool {
190
+	return WithinDuration(a.t, expected, actual, delta, msgAndArgs...)
191
+}
192
+
193
+// InDelta asserts that the two numerals are within delta of each other.
194
+//
195
+// 	 assert.InDelta(t, math.Pi, (22 / 7.0), 0.01)
196
+//
197
+// Returns whether the assertion was successful (true) or not (false).
198
+func (a *Assertions) InDelta(expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
199
+	return InDelta(a.t, expected, actual, delta, msgAndArgs...)
200
+}
201
+
202
+// InEpsilon asserts that expected and actual have a relative error less than epsilon
203
+//
204
+// Returns whether the assertion was successful (true) or not (false).
205
+func (a *Assertions) InEpsilon(expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
206
+	return InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...)
207
+}
208
+
209
+// NoError asserts that a function returned no error (i.e. `nil`).
210
+//
211
+//   actualObj, err := SomeFunction()
212
+//   if assert.NoError(err) {
213
+//	   assert.Equal(actualObj, expectedObj)
214
+//   }
215
+//
216
+// Returns whether the assertion was successful (true) or not (false).
217
+func (a *Assertions) NoError(theError error, msgAndArgs ...interface{}) bool {
218
+	return NoError(a.t, theError, msgAndArgs...)
219
+}
220
+
221
+// Error asserts that a function returned an error (i.e. not `nil`).
222
+//
223
+//   actualObj, err := SomeFunction()
224
+//   if assert.Error(err, "An error was expected") {
225
+//	   assert.Equal(err, expectedError)
226
+//   }
227
+//
228
+// Returns whether the assertion was successful (true) or not (false).
229
+func (a *Assertions) Error(theError error, msgAndArgs ...interface{}) bool {
230
+	return Error(a.t, theError, msgAndArgs...)
231
+}
232
+
233
+// EqualError asserts that a function returned an error (i.e. not `nil`)
234
+// and that it is equal to the provided error.
235
+//
236
+//   actualObj, err := SomeFunction()
237
+//   if assert.Error(err, "An error was expected") {
238
+//	   assert.Equal(err, expectedError)
239
+//   }
240
+//
241
+// Returns whether the assertion was successful (true) or not (false).
242
+func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) bool {
243
+	return EqualError(a.t, theError, errString, msgAndArgs...)
244
+}
245
+
246
+// Regexp asserts that a specified regexp matches a string.
247
+//
248
+//  assert.Regexp(t, regexp.MustCompile("start"), "it's starting")
249
+//  assert.Regexp(t, "start...$", "it's not starting")
250
+//
251
+// Returns whether the assertion was successful (true) or not (false).
252
+func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
253
+	return Regexp(a.t, rx, str, msgAndArgs...)
254
+}
255
+
256
+// NotRegexp asserts that a specified regexp does not match a string.
257
+//
258
+//  assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting")
259
+//  assert.NotRegexp(t, "^start", "it's not starting")
260
+//
261
+// Returns whether the assertion was successful (true) or not (false).
262
+func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
263
+	return NotRegexp(a.t, rx, str, msgAndArgs...)
264
+}
265
+
266
+// Zero asserts that i is the zero value for its type and returns the truth.
267
+func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) bool {
268
+	return Zero(a.t, i, msgAndArgs...)
269
+}
270
+
271
+// NotZero asserts that i is not the zero value for its type and returns the truth.
272
+func (a *Assertions) NotZero(i interface{}, msgAndArgs ...interface{}) bool {
273
+	return NotZero(a.t, i, msgAndArgs...)
274
+}
0 275
new file mode 100644
... ...
@@ -0,0 +1,157 @@
0
+package assert
1
+
2
+import (
3
+	"fmt"
4
+	"net/http"
5
+	"net/http/httptest"
6
+	"net/url"
7
+	"strings"
8
+)
9
+
10
+// httpCode is a helper that returns HTTP code of the response. It returns -1
11
+// if building a new request fails.
12
+func httpCode(handler http.HandlerFunc, method, url string, values url.Values) int {
13
+	w := httptest.NewRecorder()
14
+	req, err := http.NewRequest(method, url+"?"+values.Encode(), nil)
15
+	if err != nil {
16
+		return -1
17
+	}
18
+	handler(w, req)
19
+	return w.Code
20
+}
21
+
22
+// HTTPSuccess asserts that a specified handler returns a success status code.
23
+//
24
+//  assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil)
25
+//
26
+// Returns whether the assertion was successful (true) or not (false).
27
+func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, values url.Values) bool {
28
+	code := httpCode(handler, method, url, values)
29
+	if code == -1 {
30
+		return false
31
+	}
32
+	return code >= http.StatusOK && code <= http.StatusPartialContent
33
+}
34
+
35
+// HTTPRedirect asserts that a specified handler returns a redirect status code.
36
+//
37
+//  assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
38
+//
39
+// Returns whether the assertion was successful (true) or not (false).
40
+func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, values url.Values) bool {
41
+	code := httpCode(handler, method, url, values)
42
+	if code == -1 {
43
+		return false
44
+	}
45
+	return code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect
46
+}
47
+
48
+// HTTPError asserts that a specified handler returns an error status code.
49
+//
50
+//  assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
51
+//
52
+// Returns whether the assertion was successful (true) or not (false).
53
+func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values url.Values) bool {
54
+	code := httpCode(handler, method, url, values)
55
+	if code == -1 {
56
+		return false
57
+	}
58
+	return code >= http.StatusBadRequest
59
+}
60
+
61
+// HTTPBody is a helper that returns HTTP body of the response. It returns
62
+// empty string if building a new request fails.
63
+func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) string {
64
+	w := httptest.NewRecorder()
65
+	req, err := http.NewRequest(method, url+"?"+values.Encode(), nil)
66
+	if err != nil {
67
+		return ""
68
+	}
69
+	handler(w, req)
70
+	return w.Body.String()
71
+}
72
+
73
+// HTTPBodyContains asserts that a specified handler returns a
74
+// body that contains a string.
75
+//
76
+//  assert.HTTPBodyContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky")
77
+//
78
+// Returns whether the assertion was successful (true) or not (false).
79
+func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}) bool {
80
+	body := HTTPBody(handler, method, url, values)
81
+
82
+	contains := strings.Contains(body, fmt.Sprint(str))
83
+	if !contains {
84
+		Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body))
85
+	}
86
+
87
+	return contains
88
+}
89
+
90
+// HTTPBodyNotContains asserts that a specified handler returns a
91
+// body that does not contain a string.
92
+//
93
+//  assert.HTTPBodyNotContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky")
94
+//
95
+// Returns whether the assertion was successful (true) or not (false).
96
+func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}) bool {
97
+	body := HTTPBody(handler, method, url, values)
98
+
99
+	contains := strings.Contains(body, fmt.Sprint(str))
100
+	if contains {
101
+		Fail(t, "Expected response body for %s to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body)
102
+	}
103
+
104
+	return !contains
105
+}
106
+
107
+//
108
+// Assertions Wrappers
109
+//
110
+
111
+// HTTPSuccess asserts that a specified handler returns a success status code.
112
+//
113
+//  assert.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil)
114
+//
115
+// Returns whether the assertion was successful (true) or not (false).
116
+func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method, url string, values url.Values) bool {
117
+	return HTTPSuccess(a.t, handler, method, url, values)
118
+}
119
+
120
+// HTTPRedirect asserts that a specified handler returns a redirect status code.
121
+//
122
+//  assert.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
123
+//
124
+// Returns whether the assertion was successful (true) or not (false).
125
+func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method, url string, values url.Values) bool {
126
+	return HTTPRedirect(a.t, handler, method, url, values)
127
+}
128
+
129
+// HTTPError asserts that a specified handler returns an error status code.
130
+//
131
+//  assert.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
132
+//
133
+// Returns whether the assertion was successful (true) or not (false).
134
+func (a *Assertions) HTTPError(handler http.HandlerFunc, method, url string, values url.Values) bool {
135
+	return HTTPError(a.t, handler, method, url, values)
136
+}
137
+
138
+// HTTPBodyContains asserts that a specified handler returns a
139
+// body that contains a string.
140
+//
141
+//  assert.HTTPBodyContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky")
142
+//
143
+// Returns whether the assertion was successful (true) or not (false).
144
+func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method, url string, values url.Values, str interface{}) bool {
145
+	return HTTPBodyContains(a.t, handler, method, url, values, str)
146
+}
147
+
148
+// HTTPBodyNotContains asserts that a specified handler returns a
149
+// body that does not contain a string.
150
+//
151
+//  assert.HTTPBodyNotContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky")
152
+//
153
+// Returns whether the assertion was successful (true) or not (false).
154
+func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method, url string, values url.Values, str interface{}) bool {
155
+	return HTTPBodyNotContains(a.t, handler, method, url, values, str)
156
+}
0 157
new file mode 100644
... ...
@@ -0,0 +1,43 @@
0
+// Provides a system by which it is possible to mock your objects and verify calls are happening as expected.
1
+//
2
+// Example Usage
3
+//
4
+// The mock package provides an object, Mock, that tracks activity on another object.  It is usually
5
+// embedded into a test object as shown below:
6
+//
7
+//   type MyTestObject struct {
8
+//     // add a Mock object instance
9
+//     mock.Mock
10
+//
11
+//     // other fields go here as normal
12
+//   }
13
+//
14
+// When implementing the methods of an interface, you wire your functions up
15
+// to call the Mock.Called(args...) method, and return the appropriate values.
16
+//
17
+// For example, to mock a method that saves the name and age of a person and returns
18
+// the year of their birth or an error, you might write this:
19
+//
20
+//     func (o *MyTestObject) SavePersonDetails(firstname, lastname string, age int) (int, error) {
21
+//       args := o.Called(firstname, lastname, age)
22
+//       return args.Int(0), args.Error(1)
23
+//     }
24
+//
25
+// The Int, Error and Bool methods are examples of strongly typed getters that take the argument
26
+// index position. Given this argument list:
27
+//
28
+//     (12, true, "Something")
29
+//
30
+// You could read them out strongly typed like this:
31
+//
32
+//     args.Int(0)
33
+//     args.Bool(1)
34
+//     args.String(2)
35
+//
36
+// For objects of your own type, use the generic Arguments.Get(index) method and make a type assertion:
37
+//
38
+//     return args.Get(0).(*MyObject), args.Get(1).(*AnotherObjectOfMine)
39
+//
40
+// This may cause a panic if the object you are getting is nil (the type assertion will fail), in those
41
+// cases you should check for nil first.
42
+package mock
0 43
new file mode 100644
... ...
@@ -0,0 +1,594 @@
0
+package mock
1
+
2
+import (
3
+	"fmt"
4
+	"reflect"
5
+	"runtime"
6
+	"strings"
7
+	"sync"
8
+	"time"
9
+
10
+	"github.com/stretchr/objx"
11
+	"github.com/stretchr/testify/assert"
12
+)
13
+
14
+// TestingT is an interface wrapper around *testing.T
15
+type TestingT interface {
16
+	Logf(format string, args ...interface{})
17
+	Errorf(format string, args ...interface{})
18
+}
19
+
20
+/*
21
+	Call
22
+*/
23
+
24
+// Call represents a method call and is used for setting expectations,
25
+// as well as recording activity.
26
+type Call struct {
27
+
28
+	// The name of the method that was or will be called.
29
+	Method string
30
+
31
+	// Holds the arguments of the method.
32
+	Arguments Arguments
33
+
34
+	// Holds the arguments that should be returned when
35
+	// this method is called.
36
+	ReturnArguments Arguments
37
+
38
+	// The number of times to return the return arguments when setting
39
+	// expectations. 0 means to always return the value.
40
+	Repeatability int
41
+
42
+	// Holds a channel that will be used to block the Return until it either
43
+	// recieves a message or is closed. nil means it returns immediately.
44
+	WaitFor <-chan time.Time
45
+
46
+	// Holds a handler used to manipulate arguments content that are passed by
47
+	// reference. It's useful when mocking methods such as unmarshalers or
48
+	// decoders.
49
+	Run func(Arguments)
50
+}
51
+
52
+// Mock is the workhorse used to track activity on another object.
53
+// For an example of its usage, refer to the "Example Usage" section at the top of this document.
54
+type Mock struct {
55
+
56
+	// The method name that is currently
57
+	// being referred to by the On method.
58
+	onMethodName string
59
+
60
+	// An array of the arguments that are
61
+	// currently being referred to by the On method.
62
+	onMethodArguments Arguments
63
+
64
+	// Represents the calls that are expected of
65
+	// an object.
66
+	ExpectedCalls []Call
67
+
68
+	// Holds the calls that were made to this mocked object.
69
+	Calls []Call
70
+
71
+	// TestData holds any data that might be useful for testing.  Testify ignores
72
+	// this data completely allowing you to do whatever you like with it.
73
+	testData objx.Map
74
+
75
+	mutex sync.Mutex
76
+}
77
+
78
+// TestData holds any data that might be useful for testing.  Testify ignores
79
+// this data completely allowing you to do whatever you like with it.
80
+func (m *Mock) TestData() objx.Map {
81
+
82
+	if m.testData == nil {
83
+		m.testData = make(objx.Map)
84
+	}
85
+
86
+	return m.testData
87
+}
88
+
89
+/*
90
+	Setting expectations
91
+*/
92
+
93
+// On starts a description of an expectation of the specified method
94
+// being called.
95
+//
96
+//     Mock.On("MyMethod", arg1, arg2)
97
+func (m *Mock) On(methodName string, arguments ...interface{}) *Mock {
98
+	m.onMethodName = methodName
99
+	m.onMethodArguments = arguments
100
+
101
+	for _, arg := range arguments {
102
+		if v := reflect.ValueOf(arg); v.Kind() == reflect.Func {
103
+			panic(fmt.Sprintf("cannot use Func in expectations. Use mock.AnythingOfType(\"%T\")", arg))
104
+		}
105
+	}
106
+
107
+	return m
108
+}
109
+
110
+// Return finishes a description of an expectation of the method (and arguments)
111
+// specified in the most recent On method call.
112
+//
113
+//     Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2)
114
+func (m *Mock) Return(returnArguments ...interface{}) *Mock {
115
+	m.mutex.Lock()
116
+	defer m.mutex.Unlock()
117
+
118
+	m.ExpectedCalls = append(m.ExpectedCalls, Call{m.onMethodName, m.onMethodArguments, returnArguments, 0, nil, nil})
119
+	return m
120
+}
121
+
122
+// Once indicates that that the mock should only return the value once.
123
+//
124
+//    Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Once()
125
+func (m *Mock) Once() {
126
+	m.mutex.Lock()
127
+	m.ExpectedCalls[len(m.ExpectedCalls)-1].Repeatability = 1
128
+	m.mutex.Unlock()
129
+}
130
+
131
+// Twice indicates that that the mock should only return the value twice.
132
+//
133
+//    Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Twice()
134
+func (m *Mock) Twice() {
135
+	m.mutex.Lock()
136
+	m.ExpectedCalls[len(m.ExpectedCalls)-1].Repeatability = 2
137
+	m.mutex.Unlock()
138
+}
139
+
140
+// Times indicates that that the mock should only return the indicated number
141
+// of times.
142
+//
143
+//    Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Times(5)
144
+func (m *Mock) Times(i int) {
145
+	m.mutex.Lock()
146
+	m.ExpectedCalls[len(m.ExpectedCalls)-1].Repeatability = i
147
+	m.mutex.Unlock()
148
+}
149
+
150
+// WaitUntil sets the channel that will block the mock's return until its closed
151
+// or a message is received.
152
+//
153
+//    Mock.On("MyMethod", arg1, arg2).WaitUntil(time.After(time.Second))
154
+func (m *Mock) WaitUntil(w <-chan time.Time) *Mock {
155
+	m.mutex.Lock()
156
+	m.ExpectedCalls[len(m.ExpectedCalls)-1].WaitFor = w
157
+	m.mutex.Unlock()
158
+	return m
159
+}
160
+
161
+// After sets how long to block until the call returns
162
+//
163
+//    Mock.On("MyMethod", arg1, arg2).After(time.Second)
164
+func (m *Mock) After(d time.Duration) *Mock {
165
+	return m.WaitUntil(time.After(d))
166
+}
167
+
168
+// Run sets a handler to be called before returning. It can be used when
169
+// mocking a method such as unmarshalers that takes a pointer to a struct and
170
+// sets properties in such struct
171
+//
172
+//    Mock.On("Unmarshal", AnythingOfType("*map[string]interface{}").Return().Run(function(args Arguments) {
173
+//    	arg := args.Get(0).(*map[string]interface{})
174
+//    	arg["foo"] = "bar"
175
+//    })
176
+func (m *Mock) Run(fn func(Arguments)) *Mock {
177
+	m.mutex.Lock()
178
+	m.ExpectedCalls[len(m.ExpectedCalls)-1].Run = fn
179
+	m.mutex.Unlock()
180
+	return m
181
+}
182
+
183
+/*
184
+	Recording and responding to activity
185
+*/
186
+
187
+func (m *Mock) findExpectedCall(method string, arguments ...interface{}) (int, *Call) {
188
+	for i, call := range m.expectedCalls() {
189
+		if call.Method == method && call.Repeatability > -1 {
190
+
191
+			_, diffCount := call.Arguments.Diff(arguments)
192
+			if diffCount == 0 {
193
+				return i, &call
194
+			}
195
+
196
+		}
197
+	}
198
+	return -1, nil
199
+}
200
+
201
+func (m *Mock) findClosestCall(method string, arguments ...interface{}) (bool, *Call) {
202
+	diffCount := 0
203
+	var closestCall *Call = nil
204
+
205
+	for _, call := range m.expectedCalls() {
206
+		if call.Method == method {
207
+
208
+			_, tempDiffCount := call.Arguments.Diff(arguments)
209
+			if tempDiffCount < diffCount || diffCount == 0 {
210
+				diffCount = tempDiffCount
211
+				closestCall = &call
212
+			}
213
+
214
+		}
215
+	}
216
+
217
+	if closestCall == nil {
218
+		return false, nil
219
+	}
220
+
221
+	return true, closestCall
222
+}
223
+
224
+func callString(method string, arguments Arguments, includeArgumentValues bool) string {
225
+
226
+	var argValsString string = ""
227
+	if includeArgumentValues {
228
+		var argVals []string
229
+		for argIndex, arg := range arguments {
230
+			argVals = append(argVals, fmt.Sprintf("%d: %v", argIndex, arg))
231
+		}
232
+		argValsString = fmt.Sprintf("\n\t\t%s", strings.Join(argVals, "\n\t\t"))
233
+	}
234
+
235
+	return fmt.Sprintf("%s(%s)%s", method, arguments.String(), argValsString)
236
+}
237
+
238
+// Called tells the mock object that a method has been called, and gets an array
239
+// of arguments to return.  Panics if the call is unexpected (i.e. not preceeded by
240
+// appropriate .On .Return() calls)
241
+// If Call.WaitFor is set, blocks until the channel is closed or receives a message.
242
+func (m *Mock) Called(arguments ...interface{}) Arguments {
243
+	// get the calling function's name
244
+	pc, _, _, ok := runtime.Caller(1)
245
+	if !ok {
246
+		panic("Couldn't get the caller information")
247
+	}
248
+	functionPath := runtime.FuncForPC(pc).Name()
249
+	parts := strings.Split(functionPath, ".")
250
+	functionName := parts[len(parts)-1]
251
+
252
+	found, call := m.findExpectedCall(functionName, arguments...)
253
+
254
+	if found < 0 {
255
+		// we have to fail here - because we don't know what to do
256
+		// as the return arguments.  This is because:
257
+		//
258
+		//   a) this is a totally unexpected call to this method,
259
+		//   b) the arguments are not what was expected, or
260
+		//   c) the developer has forgotten to add an accompanying On...Return pair.
261
+
262
+		closestFound, closestCall := m.findClosestCall(functionName, arguments...)
263
+
264
+		if closestFound {
265
+			panic(fmt.Sprintf("\n\nmock: Unexpected Method Call\n-----------------------------\n\n%s\n\nThe closest call I have is: \n\n%s\n", callString(functionName, arguments, true), callString(functionName, closestCall.Arguments, true)))
266
+		} else {
267
+			panic(fmt.Sprintf("\nassert: mock: I don't know what to return because the method call was unexpected.\n\tEither do Mock.On(\"%s\").Return(...) first, or remove the %s() call.\n\tThis method was unexpected:\n\t\t%s\n\tat: %s", functionName, functionName, callString(functionName, arguments, true), assert.CallerInfo()))
268
+		}
269
+	} else {
270
+		m.mutex.Lock()
271
+		switch {
272
+		case call.Repeatability == 1:
273
+			call.Repeatability = -1
274
+			m.ExpectedCalls[found] = *call
275
+		case call.Repeatability > 1:
276
+			call.Repeatability -= 1
277
+			m.ExpectedCalls[found] = *call
278
+		}
279
+		m.mutex.Unlock()
280
+	}
281
+
282
+	// add the call
283
+	m.mutex.Lock()
284
+	m.Calls = append(m.Calls, Call{functionName, arguments, make([]interface{}, 0), 0, nil, nil})
285
+	m.mutex.Unlock()
286
+
287
+	// block if specified
288
+	if call.WaitFor != nil {
289
+		<-call.WaitFor
290
+	}
291
+
292
+	if call.Run != nil {
293
+		call.Run(arguments)
294
+	}
295
+
296
+	return call.ReturnArguments
297
+
298
+}
299
+
300
+/*
301
+	Assertions
302
+*/
303
+
304
+// AssertExpectationsForObjects asserts that everything specified with On and Return
305
+// of the specified objects was in fact called as expected.
306
+//
307
+// Calls may have occurred in any order.
308
+func AssertExpectationsForObjects(t TestingT, testObjects ...interface{}) bool {
309
+	var success bool = true
310
+	for _, obj := range testObjects {
311
+		mockObj := obj.(Mock)
312
+		success = success && mockObj.AssertExpectations(t)
313
+	}
314
+	return success
315
+}
316
+
317
+// AssertExpectations asserts that everything specified with On and Return was
318
+// in fact called as expected.  Calls may have occurred in any order.
319
+func (m *Mock) AssertExpectations(t TestingT) bool {
320
+	var somethingMissing bool = false
321
+	var failedExpectations int = 0
322
+
323
+	// iterate through each expectation
324
+	expectedCalls := m.expectedCalls()
325
+	for _, expectedCall := range expectedCalls {
326
+		switch {
327
+		case !m.methodWasCalled(expectedCall.Method, expectedCall.Arguments):
328
+			somethingMissing = true
329
+			failedExpectations++
330
+			t.Logf("\u274C\t%s(%s)", expectedCall.Method, expectedCall.Arguments.String())
331
+		case expectedCall.Repeatability > 0:
332
+			somethingMissing = true
333
+			failedExpectations++
334
+		default:
335
+			t.Logf("\u2705\t%s(%s)", expectedCall.Method, expectedCall.Arguments.String())
336
+		}
337
+	}
338
+
339
+	if somethingMissing {
340
+		t.Errorf("FAIL: %d out of %d expectation(s) were met.\n\tThe code you are testing needs to make %d more call(s).\n\tat: %s", len(expectedCalls)-failedExpectations, len(expectedCalls), failedExpectations, assert.CallerInfo())
341
+	}
342
+
343
+	return !somethingMissing
344
+}
345
+
346
+// AssertNumberOfCalls asserts that the method was called expectedCalls times.
347
+func (m *Mock) AssertNumberOfCalls(t TestingT, methodName string, expectedCalls int) bool {
348
+	var actualCalls int = 0
349
+	for _, call := range m.calls() {
350
+		if call.Method == methodName {
351
+			actualCalls++
352
+		}
353
+	}
354
+	return assert.Equal(t, expectedCalls, actualCalls, fmt.Sprintf("Expected number of calls (%d) does not match the actual number of calls (%d).", expectedCalls, actualCalls))
355
+}
356
+
357
+// AssertCalled asserts that the method was called.
358
+func (m *Mock) AssertCalled(t TestingT, methodName string, arguments ...interface{}) bool {
359
+	if !assert.True(t, m.methodWasCalled(methodName, arguments), fmt.Sprintf("The \"%s\" method should have been called with %d argument(s), but was not.", methodName, len(arguments))) {
360
+		t.Logf("%v", m.expectedCalls())
361
+		return false
362
+	}
363
+	return true
364
+}
365
+
366
+// AssertNotCalled asserts that the method was not called.
367
+func (m *Mock) AssertNotCalled(t TestingT, methodName string, arguments ...interface{}) bool {
368
+	if !assert.False(t, m.methodWasCalled(methodName, arguments), fmt.Sprintf("The \"%s\" method was called with %d argument(s), but should NOT have been.", methodName, len(arguments))) {
369
+		t.Logf("%v", m.expectedCalls())
370
+		return false
371
+	}
372
+	return true
373
+}
374
+
375
+func (m *Mock) methodWasCalled(methodName string, expected []interface{}) bool {
376
+	for _, call := range m.calls() {
377
+		if call.Method == methodName {
378
+
379
+			_, differences := Arguments(expected).Diff(call.Arguments)
380
+
381
+			if differences == 0 {
382
+				// found the expected call
383
+				return true
384
+			}
385
+
386
+		}
387
+	}
388
+	// we didn't find the expected call
389
+	return false
390
+}
391
+
392
+func (m *Mock) expectedCalls() []Call {
393
+	m.mutex.Lock()
394
+	defer m.mutex.Unlock()
395
+	return append([]Call{}, m.ExpectedCalls...)
396
+}
397
+
398
+func (m *Mock) calls() []Call {
399
+	m.mutex.Lock()
400
+	defer m.mutex.Unlock()
401
+	return append([]Call{}, m.Calls...)
402
+}
403
+
404
+/*
405
+	Arguments
406
+*/
407
+
408
+// Arguments holds an array of method arguments or return values.
409
+type Arguments []interface{}
410
+
411
+const (
412
+	// The "any" argument.  Used in Diff and Assert when
413
+	// the argument being tested shouldn't be taken into consideration.
414
+	Anything string = "mock.Anything"
415
+)
416
+
417
+// AnythingOfTypeArgument is a string that contains the type of an argument
418
+// for use when type checking.  Used in Diff and Assert.
419
+type AnythingOfTypeArgument string
420
+
421
+// AnythingOfType returns an AnythingOfTypeArgument object containing the
422
+// name of the type to check for.  Used in Diff and Assert.
423
+//
424
+// For example:
425
+//	Assert(t, AnythingOfType("string"), AnythingOfType("int"))
426
+func AnythingOfType(t string) AnythingOfTypeArgument {
427
+	return AnythingOfTypeArgument(t)
428
+}
429
+
430
+// Get Returns the argument at the specified index.
431
+func (args Arguments) Get(index int) interface{} {
432
+	if index+1 > len(args) {
433
+		panic(fmt.Sprintf("assert: arguments: Cannot call Get(%d) because there are %d argument(s).", index, len(args)))
434
+	}
435
+	return args[index]
436
+}
437
+
438
+// Is gets whether the objects match the arguments specified.
439
+func (args Arguments) Is(objects ...interface{}) bool {
440
+	for i, obj := range args {
441
+		if obj != objects[i] {
442
+			return false
443
+		}
444
+	}
445
+	return true
446
+}
447
+
448
+// Diff gets a string describing the differences between the arguments
449
+// and the specified objects.
450
+//
451
+// Returns the diff string and number of differences found.
452
+func (args Arguments) Diff(objects []interface{}) (string, int) {
453
+
454
+	var output string = "\n"
455
+	var differences int
456
+
457
+	var maxArgCount int = len(args)
458
+	if len(objects) > maxArgCount {
459
+		maxArgCount = len(objects)
460
+	}
461
+
462
+	for i := 0; i < maxArgCount; i++ {
463
+		var actual, expected interface{}
464
+
465
+		if len(objects) <= i {
466
+			actual = "(Missing)"
467
+		} else {
468
+			actual = objects[i]
469
+		}
470
+
471
+		if len(args) <= i {
472
+			expected = "(Missing)"
473
+		} else {
474
+			expected = args[i]
475
+		}
476
+
477
+		if reflect.TypeOf(expected) == reflect.TypeOf((*AnythingOfTypeArgument)(nil)).Elem() {
478
+
479
+			// type checking
480
+			if reflect.TypeOf(actual).Name() != string(expected.(AnythingOfTypeArgument)) && reflect.TypeOf(actual).String() != string(expected.(AnythingOfTypeArgument)) {
481
+				// not match
482
+				differences++
483
+				output = fmt.Sprintf("%s\t%d: \u274C  type %s != type %s - %s\n", output, i, expected, reflect.TypeOf(actual).Name(), actual)
484
+			}
485
+
486
+		} else {
487
+
488
+			// normal checking
489
+
490
+			if assert.ObjectsAreEqual(expected, Anything) || assert.ObjectsAreEqual(actual, Anything) || assert.ObjectsAreEqual(actual, expected) {
491
+				// match
492
+				output = fmt.Sprintf("%s\t%d: \u2705  %s == %s\n", output, i, actual, expected)
493
+			} else {
494
+				// not match
495
+				differences++
496
+				output = fmt.Sprintf("%s\t%d: \u274C  %s != %s\n", output, i, actual, expected)
497
+			}
498
+		}
499
+
500
+	}
501
+
502
+	if differences == 0 {
503
+		return "No differences.", differences
504
+	}
505
+
506
+	return output, differences
507
+
508
+}
509
+
510
+// Assert compares the arguments with the specified objects and fails if
511
+// they do not exactly match.
512
+func (args Arguments) Assert(t TestingT, objects ...interface{}) bool {
513
+
514
+	// get the differences
515
+	diff, diffCount := args.Diff(objects)
516
+
517
+	if diffCount == 0 {
518
+		return true
519
+	}
520
+
521
+	// there are differences... report them...
522
+	t.Logf(diff)
523
+	t.Errorf("%sArguments do not match.", assert.CallerInfo())
524
+
525
+	return false
526
+
527
+}
528
+
529
+// String gets the argument at the specified index. Panics if there is no argument, or
530
+// if the argument is of the wrong type.
531
+//
532
+// If no index is provided, String() returns a complete string representation
533
+// of the arguments.
534
+func (args Arguments) String(indexOrNil ...int) string {
535
+
536
+	if len(indexOrNil) == 0 {
537
+		// normal String() method - return a string representation of the args
538
+		var argsStr []string
539
+		for _, arg := range args {
540
+			argsStr = append(argsStr, fmt.Sprintf("%s", reflect.TypeOf(arg)))
541
+		}
542
+		return strings.Join(argsStr, ",")
543
+	} else if len(indexOrNil) == 1 {
544
+		// Index has been specified - get the argument at that index
545
+		var index int = indexOrNil[0]
546
+		var s string
547
+		var ok bool
548
+		if s, ok = args.Get(index).(string); !ok {
549
+			panic(fmt.Sprintf("assert: arguments: String(%d) failed because object wasn't correct type: %s", index, args.Get(index)))
550
+		}
551
+		return s
552
+	}
553
+
554
+	panic(fmt.Sprintf("assert: arguments: Wrong number of arguments passed to String.  Must be 0 or 1, not %d", len(indexOrNil)))
555
+
556
+}
557
+
558
+// Int gets the argument at the specified index. Panics if there is no argument, or
559
+// if the argument is of the wrong type.
560
+func (args Arguments) Int(index int) int {
561
+	var s int
562
+	var ok bool
563
+	if s, ok = args.Get(index).(int); !ok {
564
+		panic(fmt.Sprintf("assert: arguments: Int(%d) failed because object wasn't correct type: %v", index, args.Get(index)))
565
+	}
566
+	return s
567
+}
568
+
569
+// Error gets the argument at the specified index. Panics if there is no argument, or
570
+// if the argument is of the wrong type.
571
+func (args Arguments) Error(index int) error {
572
+	obj := args.Get(index)
573
+	var s error
574
+	var ok bool
575
+	if obj == nil {
576
+		return nil
577
+	}
578
+	if s, ok = obj.(error); !ok {
579
+		panic(fmt.Sprintf("assert: arguments: Error(%d) failed because object wasn't correct type: %v", index, args.Get(index)))
580
+	}
581
+	return s
582
+}
583
+
584
+// Bool gets the argument at the specified index. Panics if there is no argument, or
585
+// if the argument is of the wrong type.
586
+func (args Arguments) Bool(index int) bool {
587
+	var s bool
588
+	var ok bool
589
+	if s, ok = args.Get(index).(bool); !ok {
590
+		panic(fmt.Sprintf("assert: arguments: Bool(%d) failed because object wasn't correct type: %v", index, args.Get(index)))
591
+	}
592
+	return s
593
+}