diff --git a/Makefile b/Makefile
index 7c87d7aa9..ed57e8d1b 100644
--- a/Makefile
+++ b/Makefile
@@ -112,6 +112,7 @@ run-node:build-node
--run-mode=master --kube-conf=`pwd`/test/admin.kubeconfig \
--nodeid-file=`pwd`/test/host_id.conf \
--static-task-path=`pwd`/test/tasks \
+ --statsd.mapping-config=`pwd`/test/mapper.yml \
--log-level=debug
doc: ## build the docs
diff --git a/cmd/README.md b/cmd/README.md
index e69de29bb..c75814605 100644
--- a/cmd/README.md
+++ b/cmd/README.md
@@ -0,0 +1,19 @@
+# Component Description
+
+## API
+
+## BUILDER
+
+## ENTRANCE
+
+## EVENTLOG
+
+## GRCTL
+
+## MQ
+
+## NODE
+
+## WEBCLI
+
+## WORKER
\ No newline at end of file
diff --git a/cmd/node/option/conf.go b/cmd/node/option/conf.go
index 707d13472..440c77bbe 100644
--- a/cmd/node/option/conf.go
+++ b/cmd/node/option/conf.go
@@ -117,7 +117,17 @@ type Conf struct {
// 默认 300
LockTTL int64
- Etcd client.Config
+ Etcd client.Config
+ StatsdConfig StatsdConfig
+}
+
+//StatsdConfig StatsdConfig
+type StatsdConfig struct {
+ StatsdListenAddress string
+ StatsdListenUDP string
+ StatsdListenTCP string
+ MappingConfig string
+ ReadBuffer int
}
//AddFlags AddFlags
@@ -156,6 +166,11 @@ func (a *Conf) AddFlags(fs *pflag.FlagSet) {
//fs.StringSliceVar(&a.EventServerAddress, "event-servers", []string{"http://127.0.0.1:6363"}, "event message server address.")
fs.StringVar(&a.DBType, "db-type", "mysql", "db type mysql or etcd")
fs.StringVar(&a.DBConnectionInfo, "mysql", "admin:admin@tcp(127.0.0.1:3306)/region", "mysql db connection info")
+ fs.StringVar(&a.StatsdConfig.StatsdListenAddress, "statsd.listen-address", "", "The UDP address on which to receive statsd metric lines. DEPRECATED, use statsd.listen-udp instead.")
+ fs.StringVar(&a.StatsdConfig.StatsdListenUDP, "statsd.listen-udp", ":9125", "The UDP address on which to receive statsd metric lines. \"\" disables it.")
+ fs.StringVar(&a.StatsdConfig.StatsdListenTCP, "statsd.listen-tcp", ":9125", "The TCP address on which to receive statsd metric lines. \"\" disables it.")
+ fs.StringVar(&a.StatsdConfig.MappingConfig, "statsd.mapping-config", "", "Metric mapping configuration file name.")
+ fs.IntVar(&a.StatsdConfig.ReadBuffer, "statsd.read-buffer", 0, "Size (in bytes) of the operating system's transmit read buffer associated with the UDP connection. Please make sure the kernel parameters net.core.rmem_max is set to a value greater than the value specified.")
}
//SetLog 设置log
diff --git a/cmd/node/server/server.go b/cmd/node/server/server.go
index de98ce035..fce8519a0 100644
--- a/cmd/node/server/server.go
+++ b/cmd/node/server/server.go
@@ -28,6 +28,8 @@ import (
"github.com/goodrain/rainbond/pkg/node/core/store"
"github.com/goodrain/rainbond/pkg/node/masterserver"
"github.com/goodrain/rainbond/pkg/node/nodeserver"
+ "github.com/goodrain/rainbond/pkg/node/statsd"
+ "github.com/prometheus/client_golang/prometheus"
"github.com/Sirupsen/logrus"
@@ -86,8 +88,16 @@ func Run(c *option.Conf) error {
}
event.On(event.EXIT, ms.Stop)
}
+ //statsd exporter
+ registry := prometheus.NewRegistry()
+ exporter := statsd.CreateExporter(c.StatsdConfig, registry)
+ if err := exporter.Start(); err != nil {
+ logrus.Errorf("start statsd exporter server error,%s", err.Error())
+ return err
+ }
+
//启动API服务
- apiManager := api.NewManager(*s.Conf, s.HostNode, ms)
+ apiManager := api.NewManager(*s.Conf, s.HostNode, ms, exporter)
apiManager.Start(errChan)
defer apiManager.Stop()
diff --git a/hack/contrib/docker/chaos/plugins/build_work.py b/hack/contrib/docker/chaos/plugins/build_work.py
index fbadef758..468f55e91 100644
--- a/hack/contrib/docker/chaos/plugins/build_work.py
+++ b/hack/contrib/docker/chaos/plugins/build_work.py
@@ -330,7 +330,7 @@ class RepoBuilder():
h = self.user_cs_client
try:
h.update_service(self.service_id, json.dumps(update_items))
- self.region_client.update_service_region(self.service_id,json.dumps(update_items))
+ self.region_client.update_service_region(self.service_id, json.dumps(update_items))
except h.CallApiError, e:
self.log.error(
"网络异常,更新应用镜像名称失败. {}".format(e.message),
diff --git a/pkg/node/api/manager.go b/pkg/node/api/manager.go
index 7425431df..6cfda7782 100644
--- a/pkg/node/api/manager.go
+++ b/pkg/node/api/manager.go
@@ -24,6 +24,9 @@ import (
"time"
"github.com/goodrain/rainbond/pkg/node/masterserver"
+ "github.com/goodrain/rainbond/pkg/node/statsd"
+ "github.com/prometheus/client_golang/prometheus"
+ "github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/goodrain/rainbond/pkg/node/api/controller"
"github.com/goodrain/rainbond/pkg/node/api/model"
@@ -44,28 +47,59 @@ import (
//Manager api manager
type Manager struct {
- ctx context.Context
- cancel context.CancelFunc
- conf option.Conf
- router *chi.Mux
- node *model.HostNode
- lID client.LeaseID // lease id
- ms *masterserver.MasterServer
+ ctx context.Context
+ cancel context.CancelFunc
+ conf option.Conf
+ router *chi.Mux
+ node *model.HostNode
+ lID client.LeaseID // lease id
+ ms *masterserver.MasterServer
+ exporter *statsd.Exporter
}
//NewManager api manager
-func NewManager(c option.Conf, node *model.HostNode, ms *masterserver.MasterServer) *Manager {
+func NewManager(c option.Conf, node *model.HostNode, ms *masterserver.MasterServer, exporter *statsd.Exporter) *Manager {
r := router.Routers(c.RunMode)
ctx, cancel := context.WithCancel(context.Background())
controller.Init(&c, ms)
- return &Manager{
- ctx: ctx,
- cancel: cancel,
- conf: c,
- router: r,
- node: node,
- ms: ms,
+ m := &Manager{
+ ctx: ctx,
+ cancel: cancel,
+ conf: c,
+ router: r,
+ node: node,
+ ms: ms,
+ exporter: exporter,
}
+ m.router.Get("/app/metrics", m.HandleStatsd)
+ m.router.Get("/-/statsdreload", m.ReloadStatsdMappConfig)
+ return m
+}
+
+//ReloadStatsdMappConfig ReloadStatsdMappConfig
+func (m *Manager) ReloadStatsdMappConfig(w http.ResponseWriter, r *http.Request) {
+ if err := m.exporter.ReloadConfig(); err != nil {
+ w.Write([]byte(err.Error()))
+ w.WriteHeader(500)
+ } else {
+ w.Write([]byte("Success reload"))
+ w.WriteHeader(200)
+ }
+}
+
+//HandleStatsd statsd handle
+func (m *Manager) HandleStatsd(w http.ResponseWriter, r *http.Request) {
+ gatherers := prometheus.Gatherers{
+ prometheus.DefaultGatherer,
+ m.exporter.GetRegister(),
+ }
+ // Delegate http serving to Prometheus client library, which will call collector.Collect.
+ h := promhttp.HandlerFor(gatherers,
+ promhttp.HandlerOpts{
+ ErrorLog: logrus.StandardLogger(),
+ ErrorHandling: promhttp.ContinueOnError,
+ })
+ h.ServeHTTP(w, r)
}
//Start 启动
diff --git a/pkg/node/api/router/router.go b/pkg/node/api/router/router.go
index 2bdb7591c..3dc34fda7 100644
--- a/pkg/node/api/router/router.go
+++ b/pkg/node/api/router/router.go
@@ -55,7 +55,7 @@ func Routers(mode string) *chi.Mux {
})
r.Route("/nodes", func(r chi.Router) {
- r.Get("/fullres",controller.RegionRes)
+ r.Get("/fullres", controller.RegionRes)
r.Get("/resources", controller.Resources)
r.Get("/capres", controller.CapRes)
r.Get("/", controller.GetNodes)
@@ -67,9 +67,9 @@ func Routers(mode string) *chi.Mux {
r.Put("/{node_id}/unschedulable", controller.Cordon)
r.Put("/{node_id}/reschedulable", controller.UnCordon)
r.Put("/{node_id}/labels", controller.PutLabel)
- r.Post("/{node_id}/down", controller.DownNode) //节点下线
- r.Post("/{node_id}/up", controller.UpNode) //节点上线
- r.Get("/{node_id}/instance", controller.Instances) //节点上线
+ r.Post("/{node_id}/down", controller.DownNode) //节点下线
+ r.Post("/{node_id}/up", controller.UpNode) //节点上线
+ r.Get("/{node_id}/instance", controller.Instances) //节点上线
//历史API
r.Get("/{node}/details", controller.GetNodeDetails)
@@ -114,6 +114,6 @@ func Routers(mode string) *chi.Mux {
r.Put("/-/taskreload", controller.ReloadStaticTasks)
}
//节点监控
- r.Get("/metrics", controller.NodeExporter)
+ r.Get("/node/metrics", controller.NodeExporter)
return r
}
diff --git a/pkg/node/masterserver/task_engine.go b/pkg/node/masterserver/task_engine.go
index 81190feaf..79927b650 100644
--- a/pkg/node/masterserver/task_engine.go
+++ b/pkg/node/masterserver/task_engine.go
@@ -855,7 +855,7 @@ func (t *TaskEngine) HandleJobRecord() {
case <-t.ctx.Done():
return
case event := <-ch:
- if err:=event.Err();err!=nil{
+ if err := event.Err(); err != nil {
}
for _, ev := range event.Events {
diff --git a/pkg/node/statsd/exporter/LICENSE b/pkg/node/statsd/exporter/LICENSE
new file mode 100644
index 000000000..261eeb9e9
--- /dev/null
+++ b/pkg/node/statsd/exporter/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/pkg/node/statsd/exporter/Makefile b/pkg/node/statsd/exporter/Makefile
new file mode 100644
index 000000000..163fe771a
--- /dev/null
+++ b/pkg/node/statsd/exporter/Makefile
@@ -0,0 +1,60 @@
+# Copyright 2013 The Prometheus Authors
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+GO := GO15VENDOREXPERIMENT=1 go
+PROMU := $(GOPATH)/bin/promu
+pkgs = $(shell $(GO) list ./... | grep -v /vendor/)
+
+PREFIX ?= $(shell pwd)
+BIN_DIR ?= $(shell pwd)
+DOCKER_IMAGE_NAME ?= statsd-exporter
+DOCKER_IMAGE_TAG ?= $(subst /,-,$(shell git rev-parse --abbrev-ref HEAD))
+
+
+all: format build test
+
+style:
+ @echo ">> checking code style"
+ @! gofmt -d $(shell find . -path ./vendor -prune -o -name '*.go' -print) | grep '^'
+
+test:
+ @echo ">> running tests"
+ @$(GO) test -short $(pkgs)
+
+format:
+ @echo ">> formatting code"
+ @$(GO) fmt $(pkgs)
+
+vet:
+ @echo ">> vetting code"
+ @$(GO) vet $(pkgs)
+
+build: promu
+ @echo ">> building binaries"
+ @$(PROMU) build --prefix $(PREFIX)
+
+tarball: promu
+ @echo ">> building release tarball"
+ @$(PROMU) tarball --prefix $(PREFIX) $(BIN_DIR)
+
+docker:
+ @echo ">> building docker image"
+ @docker build -t "$(DOCKER_IMAGE_NAME):$(DOCKER_IMAGE_TAG)" .
+
+promu:
+ @GOOS=$(shell uname -s | tr A-Z a-z) \
+ GOARCH=$(subst x86_64,amd64,$(patsubst i%86,386,$(shell uname -m))) \
+ $(GO) get -u github.com/prometheus/promu
+
+
+.PHONY: all style format build test vet tarball docker promu
diff --git a/pkg/node/statsd/exporter/exporter.go b/pkg/node/statsd/exporter/exporter.go
new file mode 100644
index 000000000..fbc70a4de
--- /dev/null
+++ b/pkg/node/statsd/exporter/exporter.go
@@ -0,0 +1,595 @@
+// Copyright 2013 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package exporter
+
+import (
+ "bufio"
+ "bytes"
+ "encoding/binary"
+ "fmt"
+ "hash/fnv"
+ "io"
+ "net"
+ "regexp"
+ "strconv"
+ "strings"
+ "unicode/utf8"
+
+ "github.com/prometheus/client_golang/prometheus"
+ "github.com/prometheus/common/log"
+ "github.com/prometheus/common/model"
+)
+
+const (
+ defaultHelp = "Metric autogenerated by statsd_exporter."
+ regErrF = "A change of configuration created inconsistent metrics for " +
+ "%q. You have to restart the statsd_exporter, and you should " +
+ "consider the effects on your monitoring setup. Error: %s"
+)
+
+var (
+ illegalCharsRE = regexp.MustCompile(`[^a-zA-Z0-9_]`)
+
+ hash = fnv.New64a()
+ strBuf bytes.Buffer // Used for hashing.
+ intBuf = make([]byte, 8)
+)
+
+// hashNameAndLabels returns a hash value of the provided name string and all
+// the label names and values in the provided labels map.
+//
+// Not safe for concurrent use! (Uses a shared buffer and hasher to save on
+// allocations.)
+func hashNameAndLabels(name string, labels prometheus.Labels) uint64 {
+ hash.Reset()
+ strBuf.Reset()
+ strBuf.WriteString(name)
+ hash.Write(strBuf.Bytes())
+ binary.BigEndian.PutUint64(intBuf, model.LabelsToSignature(labels))
+ hash.Write(intBuf)
+ return hash.Sum64()
+}
+
+type CounterContainer struct {
+ Elements map[uint64]prometheus.Counter
+ Register prometheus.Registerer
+}
+
+func NewCounterContainer(Register prometheus.Registerer) *CounterContainer {
+ return &CounterContainer{
+ Elements: make(map[uint64]prometheus.Counter),
+ Register: Register,
+ }
+}
+
+func (c *CounterContainer) Get(metricName string, labels prometheus.Labels, help string) (prometheus.Counter, error) {
+ hash := hashNameAndLabels(metricName, labels)
+ counter, ok := c.Elements[hash]
+ if !ok {
+ counter = prometheus.NewCounter(prometheus.CounterOpts{
+ Name: metricName,
+ Help: help,
+ ConstLabels: labels,
+ })
+ if err := c.Register.Register(counter); err != nil {
+ return nil, err
+ }
+ c.Elements[hash] = counter
+ }
+ return counter, nil
+}
+
+type GaugeContainer struct {
+ Elements map[uint64]prometheus.Gauge
+ Register prometheus.Registerer
+}
+
+func NewGaugeContainer(Register prometheus.Registerer) *GaugeContainer {
+ return &GaugeContainer{
+ Elements: make(map[uint64]prometheus.Gauge),
+ Register: Register,
+ }
+}
+
+func (c *GaugeContainer) Get(metricName string, labels prometheus.Labels, help string) (prometheus.Gauge, error) {
+ hash := hashNameAndLabels(metricName, labels)
+ gauge, ok := c.Elements[hash]
+ if !ok {
+ gauge = prometheus.NewGauge(prometheus.GaugeOpts{
+ Name: metricName,
+ Help: help,
+ ConstLabels: labels,
+ })
+ if err := c.Register.Register(gauge); err != nil {
+ return nil, err
+ }
+ c.Elements[hash] = gauge
+ }
+ return gauge, nil
+}
+
+type SummaryContainer struct {
+ Elements map[uint64]prometheus.Summary
+ Register prometheus.Registerer
+}
+
+func NewSummaryContainer(Register prometheus.Registerer) *SummaryContainer {
+ return &SummaryContainer{
+ Elements: make(map[uint64]prometheus.Summary),
+ Register: Register,
+ }
+}
+
+func (c *SummaryContainer) Get(metricName string, labels prometheus.Labels, help string) (prometheus.Summary, error) {
+ hash := hashNameAndLabels(metricName, labels)
+ summary, ok := c.Elements[hash]
+ if !ok {
+ summary = prometheus.NewSummary(
+ prometheus.SummaryOpts{
+ Name: metricName,
+ Help: help,
+ ConstLabels: labels,
+ })
+ if err := c.Register.Register(summary); err != nil {
+ return nil, err
+ }
+ c.Elements[hash] = summary
+ }
+ return summary, nil
+}
+
+type HistogramContainer struct {
+ Elements map[uint64]prometheus.Histogram
+ mapper *MetricMapper
+ Register prometheus.Registerer
+}
+
+func NewHistogramContainer(mapper *MetricMapper, Register prometheus.Registerer) *HistogramContainer {
+ return &HistogramContainer{
+ Elements: make(map[uint64]prometheus.Histogram),
+ mapper: mapper,
+ Register: Register,
+ }
+}
+
+func (c *HistogramContainer) Get(metricName string, labels prometheus.Labels, help string, mapping *metricMapping) (prometheus.Histogram, error) {
+ hash := hashNameAndLabels(metricName, labels)
+ histogram, ok := c.Elements[hash]
+ if !ok {
+ buckets := c.mapper.Defaults.Buckets
+ if mapping != nil && mapping.Buckets != nil && len(mapping.Buckets) > 0 {
+ buckets = mapping.Buckets
+ }
+ histogram = prometheus.NewHistogram(
+ prometheus.HistogramOpts{
+ Name: metricName,
+ Help: help,
+ ConstLabels: labels,
+ Buckets: buckets,
+ })
+ c.Elements[hash] = histogram
+ if err := c.Register.Register(histogram); err != nil {
+ return nil, err
+ }
+ }
+ return histogram, nil
+}
+
+type Event interface {
+ MetricName() string
+ Value() float64
+ Labels() map[string]string
+}
+
+type CounterEvent struct {
+ metricName string
+ value float64
+ labels map[string]string
+}
+
+func (c *CounterEvent) MetricName() string { return c.metricName }
+func (c *CounterEvent) Value() float64 { return c.value }
+func (c *CounterEvent) Labels() map[string]string { return c.labels }
+
+type GaugeEvent struct {
+ metricName string
+ value float64
+ relative bool
+ labels map[string]string
+}
+
+func (g *GaugeEvent) MetricName() string { return g.metricName }
+func (g *GaugeEvent) Value() float64 { return g.value }
+func (c *GaugeEvent) Labels() map[string]string { return c.labels }
+
+type TimerEvent struct {
+ metricName string
+ value float64
+ labels map[string]string
+}
+
+func (t *TimerEvent) MetricName() string { return t.metricName }
+func (t *TimerEvent) Value() float64 { return t.value }
+func (c *TimerEvent) Labels() map[string]string { return c.labels }
+
+type Events []Event
+
+type Exporter struct {
+ Counters *CounterContainer
+ Gauges *GaugeContainer
+ Summaries *SummaryContainer
+ Histograms *HistogramContainer
+ mapper *MetricMapper
+}
+
+func escapeMetricName(metricName string) string {
+ // If a metric starts with a digit, prepend an underscore.
+ if metricName[0] >= '0' && metricName[0] <= '9' {
+ metricName = "_" + metricName
+ }
+
+ // Replace all illegal metric chars with underscores.
+ metricName = illegalCharsRE.ReplaceAllString(metricName, "_")
+ return metricName
+}
+
+func (b *Exporter) Listen(e <-chan Events) {
+ for {
+ events, ok := <-e
+ if !ok {
+ log.Debug("Channel is closed. Break out of Exporter.Listener.")
+ return
+ }
+ for _, event := range events {
+ var help string
+ metricName := ""
+ prometheusLabels := event.Labels()
+
+ mapping, labels, present := b.mapper.getMapping(event.MetricName())
+ if mapping == nil {
+ mapping = &metricMapping{}
+ }
+ if mapping.HelpText == "" {
+ help = defaultHelp
+ } else {
+ help = mapping.HelpText
+ }
+ if present {
+ metricName = mapping.Name
+ for label, value := range labels {
+ prometheusLabels[label] = value
+ }
+ } else {
+ eventsUnmapped.Inc()
+ metricName = escapeMetricName(event.MetricName())
+ }
+
+ switch ev := event.(type) {
+ case *CounterEvent:
+ // We don't accept negative values for counters. Incrementing the counter with a negative number
+ // will cause the exporter to panic. Instead we will warn and continue to the next event.
+ if event.Value() < 0.0 {
+ log.Debugf("Counter %q is: '%f' (counter must be non-negative value)", metricName, event.Value())
+ eventStats.WithLabelValues("illegal_negative_counter").Inc()
+ continue
+ }
+
+ counter, err := b.Counters.Get(
+ metricName,
+ prometheusLabels,
+ help,
+ )
+ if err == nil {
+ counter.Add(event.Value())
+
+ eventStats.WithLabelValues("counter").Inc()
+ } else {
+ log.Debugf(regErrF, metricName, err)
+ conflictingEventStats.WithLabelValues("counter").Inc()
+ }
+
+ case *GaugeEvent:
+ gauge, err := b.Gauges.Get(
+ metricName,
+ prometheusLabels,
+ help,
+ )
+
+ if err == nil {
+ if ev.relative {
+ gauge.Add(event.Value())
+ } else {
+ gauge.Set(event.Value())
+ }
+
+ eventStats.WithLabelValues("gauge").Inc()
+ } else {
+ log.Debugf(regErrF, metricName, err)
+ conflictingEventStats.WithLabelValues("gauge").Inc()
+ }
+
+ case *TimerEvent:
+ t := timerTypeDefault
+ if mapping != nil {
+ t = mapping.TimerType
+ }
+ if t == timerTypeDefault {
+ t = b.mapper.Defaults.TimerType
+ }
+
+ switch t {
+ case timerTypeHistogram:
+ histogram, err := b.Histograms.Get(
+ metricName,
+ prometheusLabels,
+ help,
+ mapping,
+ )
+ if err == nil {
+ histogram.Observe(event.Value() / 1000) // prometheus presumes seconds, statsd millisecond
+ eventStats.WithLabelValues("timer").Inc()
+ } else {
+ log.Debugf(regErrF, metricName, err)
+ conflictingEventStats.WithLabelValues("timer").Inc()
+ }
+
+ case timerTypeDefault, timerTypeSummary:
+ summary, err := b.Summaries.Get(
+ metricName,
+ prometheusLabels,
+ help,
+ )
+ if err == nil {
+ summary.Observe(event.Value())
+ eventStats.WithLabelValues("timer").Inc()
+ } else {
+ log.Debugf(regErrF, metricName, err)
+ conflictingEventStats.WithLabelValues("timer").Inc()
+ }
+
+ default:
+ panic(fmt.Sprintf("unknown timer type '%s'", t))
+ }
+
+ default:
+ log.Debugln("Unsupported event type")
+ eventStats.WithLabelValues("illegal").Inc()
+ }
+ }
+ }
+}
+
+//NewExporter new exporter
+func NewExporter(mapper *MetricMapper, Register prometheus.Registerer) *Exporter {
+ return &Exporter{
+ Counters: NewCounterContainer(Register),
+ Gauges: NewGaugeContainer(Register),
+ Summaries: NewSummaryContainer(Register),
+ Histograms: NewHistogramContainer(mapper, Register),
+ mapper: mapper,
+ }
+}
+
+func buildEvent(statType, metric string, value float64, relative bool, labels map[string]string) (Event, error) {
+ switch statType {
+ case "c":
+ return &CounterEvent{
+ metricName: metric,
+ value: float64(value),
+ labels: labels,
+ }, nil
+ case "g":
+ return &GaugeEvent{
+ metricName: metric,
+ value: float64(value),
+ relative: relative,
+ labels: labels,
+ }, nil
+ case "ms", "h":
+ return &TimerEvent{
+ metricName: metric,
+ value: float64(value),
+ labels: labels,
+ }, nil
+ case "s":
+ return nil, fmt.Errorf("No support for StatsD sets")
+ default:
+ return nil, fmt.Errorf("Bad stat type %s", statType)
+ }
+}
+
+func parseDogStatsDTagsToLabels(component string) map[string]string {
+ labels := map[string]string{}
+ tagsReceived.Inc()
+ tags := strings.Split(component, ",")
+ for _, t := range tags {
+ t = strings.TrimPrefix(t, "#")
+ kv := strings.SplitN(t, ":", 2)
+
+ if len(kv) < 2 || len(kv[1]) == 0 {
+ tagErrors.Inc()
+ log.Debugf("Malformed or empty DogStatsD tag %s in component %s", t, component)
+ continue
+ }
+
+ labels[escapeMetricName(kv[0])] = kv[1]
+ }
+ return labels
+}
+
+func lineToEvents(line string) Events {
+ events := Events{}
+ if line == "" {
+ return events
+ }
+
+ elements := strings.SplitN(line, ":", 2)
+ if len(elements) < 2 || len(elements[0]) == 0 || !utf8.ValidString(line) {
+ sampleErrors.WithLabelValues("malformed_line").Inc()
+ log.Debugln("Bad line from StatsD:", line)
+ return events
+ }
+ metric := elements[0]
+ var samples []string
+ if strings.Contains(elements[1], "|#") {
+ // using datadog extensions, disable multi-metrics
+ samples = elements[1:]
+ } else {
+ samples = strings.Split(elements[1], ":")
+ }
+samples:
+ for _, sample := range samples {
+ samplesReceived.Inc()
+ components := strings.Split(sample, "|")
+ samplingFactor := 1.0
+ if len(components) < 2 || len(components) > 4 {
+ sampleErrors.WithLabelValues("malformed_component").Inc()
+ log.Debugln("Bad component on line:", line)
+ continue
+ }
+ valueStr, statType := components[0], components[1]
+
+ var relative = false
+ if strings.Index(valueStr, "+") == 0 || strings.Index(valueStr, "-") == 0 {
+ relative = true
+ }
+
+ value, err := strconv.ParseFloat(valueStr, 64)
+ if err != nil {
+ log.Debugf("Bad value %s on line: %s", valueStr, line)
+ sampleErrors.WithLabelValues("malformed_value").Inc()
+ continue
+ }
+
+ multiplyEvents := 1
+ labels := map[string]string{}
+ if len(components) >= 3 {
+ for _, component := range components[2:] {
+ if len(component) == 0 {
+ log.Debugln("Empty component on line: ", line)
+ sampleErrors.WithLabelValues("malformed_component").Inc()
+ continue samples
+ }
+ }
+
+ for _, component := range components[2:] {
+ switch component[0] {
+ case '@':
+ if statType != "c" && statType != "ms" {
+ log.Debugln("Illegal sampling factor for non-counter metric on line", line)
+ sampleErrors.WithLabelValues("illegal_sample_factor").Inc()
+ continue
+ }
+ samplingFactor, err = strconv.ParseFloat(component[1:], 64)
+ if err != nil {
+ log.Debugf("Invalid sampling factor %s on line %s", component[1:], line)
+ sampleErrors.WithLabelValues("invalid_sample_factor").Inc()
+ }
+ if samplingFactor == 0 {
+ samplingFactor = 1
+ }
+
+ if statType == "c" {
+ value /= samplingFactor
+ } else if statType == "ms" {
+ multiplyEvents = int(1 / samplingFactor)
+ }
+ case '#':
+ labels = parseDogStatsDTagsToLabels(component)
+ default:
+ log.Debugf("Invalid sampling factor or tag section %s on line %s", components[2], line)
+ sampleErrors.WithLabelValues("invalid_sample_factor").Inc()
+ continue
+ }
+ }
+ }
+
+ for i := 0; i < multiplyEvents; i++ {
+ event, err := buildEvent(statType, metric, value, relative, labels)
+ if err != nil {
+ log.Debugf("Error building event on line %s: %s", line, err)
+ sampleErrors.WithLabelValues("illegal_event").Inc()
+ continue
+ }
+ events = append(events, event)
+ }
+ }
+ return events
+}
+
+type StatsDUDPListener struct {
+ Conn *net.UDPConn
+}
+
+func (l *StatsDUDPListener) Listen(e chan<- Events) {
+ buf := make([]byte, 65535)
+ for {
+ n, _, err := l.Conn.ReadFromUDP(buf)
+ if err != nil {
+ log.Fatal(err)
+ }
+ l.handlePacket(buf[0:n], e)
+ }
+}
+
+func (l *StatsDUDPListener) handlePacket(packet []byte, e chan<- Events) {
+ udpPackets.Inc()
+ lines := strings.Split(string(packet), "\n")
+ events := Events{}
+ for _, line := range lines {
+ linesReceived.Inc()
+ events = append(events, lineToEvents(line)...)
+ }
+ e <- events
+}
+
+type StatsDTCPListener struct {
+ Conn *net.TCPListener
+}
+
+func (l *StatsDTCPListener) Listen(e chan<- Events) {
+ defer l.Conn.Close()
+ for {
+ c, err := l.Conn.AcceptTCP()
+ if err != nil {
+ log.Fatalf("AcceptTCP failed: %v", err)
+ }
+ go l.handleConn(c, e)
+ }
+}
+
+func (l *StatsDTCPListener) handleConn(c *net.TCPConn, e chan<- Events) {
+ defer c.Close()
+
+ tcpConnections.Inc()
+
+ r := bufio.NewReader(c)
+ for {
+ line, isPrefix, err := r.ReadLine()
+ if err != nil {
+ if err != io.EOF {
+ tcpErrors.Inc()
+ log.Debugf("Read %s failed: %v", c.RemoteAddr(), err)
+ }
+ break
+ }
+ if isPrefix {
+ tcpLineTooLong.Inc()
+ log.Debugf("Read %s failed: line too long", c.RemoteAddr())
+ break
+ }
+ linesReceived.Inc()
+ e <- lineToEvents(string(line))
+ }
+}
diff --git a/pkg/node/statsd/exporter/mapper.go b/pkg/node/statsd/exporter/mapper.go
new file mode 100644
index 000000000..dd11bd664
--- /dev/null
+++ b/pkg/node/statsd/exporter/mapper.go
@@ -0,0 +1,158 @@
+// Copyright 2013 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package exporter
+
+import (
+ "fmt"
+ "io/ioutil"
+ "regexp"
+ "strings"
+ "sync"
+
+ "github.com/prometheus/client_golang/prometheus"
+ yaml "gopkg.in/yaml.v2"
+)
+
+var (
+ identifierRE = `[a-zA-Z_][a-zA-Z0-9_]+`
+ statsdMetricRE = `[a-zA-Z_](-?[a-zA-Z0-9_])+`
+
+ metricLineRE = regexp.MustCompile(`^(\*\.|` + statsdMetricRE + `\.)+(\*|` + statsdMetricRE + `)$`)
+ labelLineRE = regexp.MustCompile(`^(` + identifierRE + `)\s*=\s*"(.*)"$`)
+ metricNameRE = regexp.MustCompile(`^` + identifierRE + `$`)
+)
+
+type mapperConfigDefaults struct {
+ TimerType timerType `yaml:"timer_type"`
+ Buckets []float64 `yaml:"buckets"`
+ MatchType matchType `yaml:"match_type"`
+}
+
+//MetricMapper MetricMapper
+type MetricMapper struct {
+ Defaults mapperConfigDefaults `yaml:"defaults"`
+ Mappings []metricMapping `yaml:"mappings"`
+ mutex sync.Mutex
+}
+
+type metricMapping struct {
+ Match string `yaml:"match"`
+ Name string `yaml:"name"`
+ regex *regexp.Regexp
+ Labels prometheus.Labels `yaml:"labels"`
+ TimerType timerType `yaml:"timer_type"`
+ Buckets []float64 `yaml:"buckets"`
+ MatchType matchType `yaml:"match_type"`
+ HelpText string `yaml:"help"`
+}
+
+func (m *MetricMapper) InitFromYAMLString(fileContents string) error {
+ var n MetricMapper
+
+ if err := yaml.Unmarshal([]byte(fileContents), &n); err != nil {
+ return err
+ }
+
+ if n.Defaults.Buckets == nil || len(n.Defaults.Buckets) == 0 {
+ n.Defaults.Buckets = prometheus.DefBuckets
+ }
+
+ if n.Defaults.MatchType == matchTypeDefault {
+ n.Defaults.MatchType = matchTypeGlob
+ }
+
+ for i := range n.Mappings {
+ currentMapping := &n.Mappings[i]
+
+ // check that label is correct
+ for k := range currentMapping.Labels {
+ if !metricNameRE.MatchString(k) {
+ return fmt.Errorf("invalid label key: %s", k)
+ }
+ }
+
+ if currentMapping.Name == "" {
+ return fmt.Errorf("line %d: metric mapping didn't set a metric name", i)
+ }
+
+ if !metricNameRE.MatchString(currentMapping.Name) {
+ return fmt.Errorf("metric name '%s' doesn't match regex '%s'", currentMapping.Name, metricNameRE)
+ }
+
+ if currentMapping.MatchType == "" {
+ currentMapping.MatchType = n.Defaults.MatchType
+ }
+
+ if currentMapping.MatchType == matchTypeGlob {
+ if !metricLineRE.MatchString(currentMapping.Match) {
+ return fmt.Errorf("invalid match: %s", currentMapping.Match)
+ }
+ // Translate the glob-style metric match line into a proper regex that we
+ // can use to match metrics later on.
+ metricRe := strings.Replace(currentMapping.Match, ".", "\\.", -1)
+ metricRe = strings.Replace(metricRe, "*", "([^.]*)", -1)
+ currentMapping.regex = regexp.MustCompile("^" + metricRe + "$")
+ } else {
+ currentMapping.regex = regexp.MustCompile(currentMapping.Match)
+ }
+
+ if currentMapping.TimerType == "" {
+ currentMapping.TimerType = n.Defaults.TimerType
+ }
+
+ if currentMapping.Buckets == nil || len(currentMapping.Buckets) == 0 {
+ currentMapping.Buckets = n.Defaults.Buckets
+ }
+
+ }
+
+ m.mutex.Lock()
+ defer m.mutex.Unlock()
+
+ m.Defaults = n.Defaults
+ m.Mappings = n.Mappings
+
+ mappingsCount.Set(float64(len(n.Mappings)))
+
+ return nil
+}
+
+func (m *MetricMapper) InitFromFile(fileName string) error {
+ mappingStr, err := ioutil.ReadFile(fileName)
+ if err != nil {
+ return err
+ }
+ return m.InitFromYAMLString(string(mappingStr))
+}
+
+func (m *MetricMapper) getMapping(statsdMetric string) (*metricMapping, prometheus.Labels, bool) {
+ m.mutex.Lock()
+ defer m.mutex.Unlock()
+
+ for _, mapping := range m.Mappings {
+ matches := mapping.regex.FindStringSubmatchIndex(statsdMetric)
+ if len(matches) == 0 {
+ continue
+ }
+
+ labels := prometheus.Labels{}
+ for label, valueExpr := range mapping.Labels {
+ value := mapping.regex.ExpandString([]byte{}, valueExpr, statsdMetric, matches)
+ labels[label] = string(value)
+ }
+ return &mapping, labels, true
+ }
+
+ return nil, nil, false
+}
diff --git a/pkg/node/statsd/exporter/match.go b/pkg/node/statsd/exporter/match.go
new file mode 100644
index 000000000..f594d43ec
--- /dev/null
+++ b/pkg/node/statsd/exporter/match.go
@@ -0,0 +1,41 @@
+// Copyright 2013 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package exporter
+
+import "fmt"
+
+type matchType string
+
+const (
+ matchTypeGlob matchType = "glob"
+ matchTypeRegex matchType = "regex"
+ matchTypeDefault matchType = ""
+)
+
+func (t *matchType) UnmarshalYAML(unmarshal func(interface{}) error) error {
+ var v string
+ if err := unmarshal(&v); err != nil {
+ return err
+ }
+
+ switch matchType(v) {
+ case matchTypeRegex:
+ *t = matchTypeRegex
+ case matchTypeGlob, matchTypeDefault:
+ *t = matchTypeGlob
+ default:
+ return fmt.Errorf("invalid match type %q", v)
+ }
+ return nil
+}
diff --git a/pkg/node/statsd/exporter/telemetry.go b/pkg/node/statsd/exporter/telemetry.go
new file mode 100644
index 000000000..bc6459260
--- /dev/null
+++ b/pkg/node/statsd/exporter/telemetry.go
@@ -0,0 +1,122 @@
+// Copyright 2013 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package exporter
+
+import (
+ "github.com/prometheus/client_golang/prometheus"
+)
+
+var (
+ eventStats = prometheus.NewCounterVec(
+ prometheus.CounterOpts{
+ Name: "statsd_exporter_events_total",
+ Help: "The total number of StatsD events seen.",
+ },
+ []string{"type"},
+ )
+ eventsUnmapped = prometheus.NewCounter(prometheus.CounterOpts{
+ Name: "statsd_exporter_events_unmapped_total",
+ Help: "The total number of StatsD events no mapping was found for.",
+ })
+ udpPackets = prometheus.NewCounter(
+ prometheus.CounterOpts{
+ Name: "statsd_exporter_udp_packets_total",
+ Help: "The total number of StatsD packets received over UDP.",
+ },
+ )
+ tcpConnections = prometheus.NewCounter(
+ prometheus.CounterOpts{
+ Name: "statsd_exporter_tcp_connections_total",
+ Help: "The total number of TCP connections handled.",
+ },
+ )
+ tcpErrors = prometheus.NewCounter(
+ prometheus.CounterOpts{
+ Name: "statsd_exporter_tcp_connection_errors_total",
+ Help: "The number of errors encountered reading from TCP.",
+ },
+ )
+ tcpLineTooLong = prometheus.NewCounter(
+ prometheus.CounterOpts{
+ Name: "statsd_exporter_tcp_too_long_lines_total",
+ Help: "The number of lines discarded due to being too long.",
+ },
+ )
+ linesReceived = prometheus.NewCounter(
+ prometheus.CounterOpts{
+ Name: "statsd_exporter_lines_total",
+ Help: "The total number of StatsD lines received.",
+ },
+ )
+ samplesReceived = prometheus.NewCounter(
+ prometheus.CounterOpts{
+ Name: "statsd_exporter_samples_total",
+ Help: "The total number of StatsD samples received.",
+ },
+ )
+ sampleErrors = prometheus.NewCounterVec(
+ prometheus.CounterOpts{
+ Name: "statsd_exporter_sample_errors_total",
+ Help: "The total number of errors parsing StatsD samples.",
+ },
+ []string{"reason"},
+ )
+ tagsReceived = prometheus.NewCounter(
+ prometheus.CounterOpts{
+ Name: "statsd_exporter_tags_total",
+ Help: "The total number of DogStatsD tags processed.",
+ },
+ )
+ tagErrors = prometheus.NewCounter(
+ prometheus.CounterOpts{
+ Name: "statsd_exporter_tag_errors_total",
+ Help: "The number of errors parsign DogStatsD tags.",
+ },
+ )
+ ConfigLoads = prometheus.NewCounterVec(
+ prometheus.CounterOpts{
+ Name: "statsd_exporter_config_reloads_total",
+ Help: "The number of configuration reloads.",
+ },
+ []string{"outcome"},
+ )
+ mappingsCount = prometheus.NewGauge(prometheus.GaugeOpts{
+ Name: "statsd_exporter_loaded_mappings",
+ Help: "The current number of configured metric mappings.",
+ })
+ conflictingEventStats = prometheus.NewCounterVec(
+ prometheus.CounterOpts{
+ Name: "statsd_exporter_events_conflict_total",
+ Help: "The total number of StatsD events with conflicting names.",
+ },
+ []string{"type"},
+ )
+)
+
+//MetryInit init
+func MetryInit(registry *prometheus.Registry) {
+ registry.MustRegister(eventStats)
+ registry.MustRegister(udpPackets)
+ registry.MustRegister(tcpConnections)
+ registry.MustRegister(tcpErrors)
+ registry.MustRegister(tcpLineTooLong)
+ registry.MustRegister(linesReceived)
+ registry.MustRegister(samplesReceived)
+ registry.MustRegister(sampleErrors)
+ registry.MustRegister(tagsReceived)
+ registry.MustRegister(tagErrors)
+ registry.MustRegister(ConfigLoads)
+ registry.MustRegister(mappingsCount)
+ registry.MustRegister(conflictingEventStats)
+}
diff --git a/pkg/node/statsd/exporter/timer.go b/pkg/node/statsd/exporter/timer.go
new file mode 100644
index 000000000..f507c9653
--- /dev/null
+++ b/pkg/node/statsd/exporter/timer.go
@@ -0,0 +1,41 @@
+// Copyright 2013 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package exporter
+
+import "fmt"
+
+type timerType string
+
+const (
+ timerTypeHistogram timerType = "histogram"
+ timerTypeSummary timerType = "summary"
+ timerTypeDefault timerType = ""
+)
+
+func (t *timerType) UnmarshalYAML(unmarshal func(interface{}) error) error {
+ var v string
+ if err := unmarshal(&v); err != nil {
+ return err
+ }
+
+ switch timerType(v) {
+ case timerTypeHistogram:
+ *t = timerTypeHistogram
+ case timerTypeSummary, timerTypeDefault:
+ *t = timerTypeSummary
+ default:
+ return fmt.Errorf("invalid timer type '%s'", v)
+ }
+ return nil
+}
diff --git a/pkg/node/statsd/statsd_export.go b/pkg/node/statsd/statsd_export.go
new file mode 100644
index 000000000..2500f4eb6
--- /dev/null
+++ b/pkg/node/statsd/statsd_export.go
@@ -0,0 +1,223 @@
+// RAINBOND, Application Management Platform
+// Copyright (C) 2014-2017 Goodrain Co., Ltd.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version. For any non-GPL usage of Rainbond,
+// one or multiple Commercial Licenses authorized by Goodrain Co., Ltd.
+// must be obtained first.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+package statsd
+
+import (
+ "fmt"
+ "net"
+ "strconv"
+ "yiyun/common/log"
+
+ "github.com/Sirupsen/logrus"
+ "github.com/howeyc/fsnotify"
+ "github.com/prometheus/client_golang/prometheus"
+ "github.com/prometheus/common/version"
+
+ "github.com/goodrain/rainbond/cmd/node/option"
+ "github.com/goodrain/rainbond/pkg/node/statsd/exporter"
+)
+
+//Exporter receive statsd metric and export prometheus metric
+type Exporter struct {
+ statsdListenAddress string
+ statsdListenUDP string
+ statsdListenTCP string
+ mappingConfig string
+ readBuffer int
+ exporter *exporter.Exporter
+ register *prometheus.Registry
+ mapper *exporter.MetricMapper
+}
+
+//CreateExporter create a exporter
+func CreateExporter(sc option.StatsdConfig, register *prometheus.Registry) *Exporter {
+ exp := &Exporter{
+ statsdListenAddress: sc.StatsdListenAddress,
+ statsdListenTCP: sc.StatsdListenTCP,
+ statsdListenUDP: sc.StatsdListenUDP,
+ readBuffer: sc.ReadBuffer,
+ mappingConfig: sc.MappingConfig,
+ register: register,
+ }
+ exporter.MetryInit(register)
+ return exp
+}
+
+//Start Start
+func (e *Exporter) Start() error {
+ e.register.Register(version.NewCollector("statsd_exporter"))
+ if e.statsdListenAddress != "" {
+ logrus.Warnln("Warning: statsd.listen-address is DEPRECATED, please use statsd.listen-udp instead.")
+ e.statsdListenUDP = e.statsdListenAddress
+ }
+
+ if e.statsdListenUDP == "" && e.statsdListenTCP == "" {
+ logrus.Fatalln("At least one of UDP/TCP listeners must be specified.")
+ return fmt.Errorf("At least one of UDP/TCP listeners must be specified")
+ }
+
+ logrus.Infoln("Starting StatsD -> Prometheus Exporter", version.Info())
+ logrus.Infoln("Build context", version.BuildContext())
+ logrus.Infof("Accepting StatsD Traffic: UDP %v, TCP %v", e.statsdListenUDP, e.statsdListenTCP)
+
+ events := make(chan exporter.Events, 1024)
+
+ if e.statsdListenUDP != "" {
+ udpListenAddr := udpAddrFromString(e.statsdListenUDP)
+ uconn, err := net.ListenUDP("udp", udpListenAddr)
+ if err != nil {
+ return err
+ }
+ if e.readBuffer != 0 {
+ err = uconn.SetReadBuffer(e.readBuffer)
+ if err != nil {
+ return err
+ }
+ }
+ ul := &exporter.StatsDUDPListener{Conn: uconn}
+ go ul.Listen(events)
+ }
+
+ if e.statsdListenTCP != "" {
+ tcpListenAddr := tcpAddrFromString(e.statsdListenTCP)
+ tconn, err := net.ListenTCP("tcp", tcpListenAddr)
+ if err != nil {
+ return err
+ }
+ tl := &exporter.StatsDTCPListener{Conn: tconn}
+ go tl.Listen(events)
+ }
+
+ mapper := &exporter.MetricMapper{}
+ if e.mappingConfig != "" {
+ err := mapper.InitFromFile(e.mappingConfig)
+ if err != nil {
+ log.Fatal("Error loading config:", err)
+ return err
+ }
+ //观察文件变化进行重新reload是有风险的,采用API重新加载
+ //go watchConfig(e.mappingConfig, mapper)
+ }
+ exporter := exporter.NewExporter(mapper, e.register)
+ e.exporter = exporter
+ e.mapper = mapper
+ go exporter.Listen(events)
+ return nil
+}
+
+// Describe implements the prometheus.Collector interface.
+func (e *Exporter) Describe(ch chan<- *prometheus.Desc) {
+
+}
+
+// Collect implements the prometheus.Collector interface.
+func (e *Exporter) Collect(ch chan<- prometheus.Metric) {
+}
+
+//GetRegister GetRegister
+func (e *Exporter) GetRegister() *prometheus.Registry {
+ return e.register
+}
+
+func ipPortFromString(addr string) (*net.IPAddr, int) {
+ host, portStr, err := net.SplitHostPort(addr)
+ if err != nil {
+ logrus.Fatal("Bad StatsD listening address", addr)
+ }
+
+ if host == "" {
+ host = "0.0.0.0"
+ }
+ ip, err := net.ResolveIPAddr("ip", host)
+ if err != nil {
+ logrus.Fatalf("Unable to resolve %s: %s", host, err)
+ }
+
+ port, err := strconv.Atoi(portStr)
+ if err != nil || port < 0 || port > 65535 {
+ logrus.Fatalf("Bad port %s: %s", portStr, err)
+ }
+
+ return ip, port
+}
+
+func udpAddrFromString(addr string) *net.UDPAddr {
+ ip, port := ipPortFromString(addr)
+ return &net.UDPAddr{
+ IP: ip.IP,
+ Port: port,
+ Zone: ip.Zone,
+ }
+}
+
+func tcpAddrFromString(addr string) *net.TCPAddr {
+ ip, port := ipPortFromString(addr)
+ return &net.TCPAddr{
+ IP: ip.IP,
+ Port: port,
+ Zone: ip.Zone,
+ }
+}
+
+func watchConfig(fileName string, mapper *exporter.MetricMapper) {
+ watcher, err := fsnotify.NewWatcher()
+ if err != nil {
+ logrus.Fatal(err)
+ }
+
+ err = watcher.WatchFlags(fileName, fsnotify.FSN_MODIFY)
+ if err != nil {
+ logrus.Fatal(err)
+ }
+
+ for {
+ select {
+ case ev := <-watcher.Event:
+ logrus.Infof("Config file changed (%s), attempting reload", ev)
+ err = mapper.InitFromFile(fileName)
+ if err != nil {
+ logrus.Errorln("Error reloading config:", err)
+ exporter.ConfigLoads.WithLabelValues("failure").Inc()
+ } else {
+ logrus.Infoln("Config reloaded successfully")
+ exporter.ConfigLoads.WithLabelValues("success").Inc()
+ }
+ // Re-add the file watcher since it can get lost on some changes. E.g.
+ // saving a file with vim results in a RENAME-MODIFY-DELETE event
+ // sequence, after which the newly written file is no longer watched.
+ err = watcher.WatchFlags(fileName, fsnotify.FSN_MODIFY)
+ case err := <-watcher.Error:
+ logrus.Errorln("Error watching config:", err)
+ }
+ }
+}
+
+//ReloadConfig reload mapper config file
+func (e *Exporter) ReloadConfig() (err error) {
+ logrus.Infof("Config file changed, attempting reload")
+ err = e.mapper.InitFromFile(e.mappingConfig)
+ if err != nil {
+ logrus.Errorln("Error reloading config:", err)
+ exporter.ConfigLoads.WithLabelValues("failure").Inc()
+ } else {
+ logrus.Infoln("Config reloaded successfully")
+ exporter.ConfigLoads.WithLabelValues("success").Inc()
+ }
+ return
+}
diff --git a/test/mapper.yml b/test/mapper.yml
new file mode 100644
index 000000000..978007169
--- /dev/null
+++ b/test/mapper.yml
@@ -0,0 +1,16 @@
+#
+mappings:
+- match: "*.*.*.request.*"
+ name: "app_http_request"
+ labels:
+ service_id: "$1"
+ port: "$2"
+ protocol: $3
+ method: "$4"
+- match: "*.*.*.request.unusual.*"
+ name: "app_http_request_unusual"
+ labels:
+ service_id: "$1"
+ port: "$2"
+ protocol: $3
+ code: "$4"
\ No newline at end of file
diff --git a/vendor/github.com/howeyc/fsnotify/AUTHORS b/vendor/github.com/howeyc/fsnotify/AUTHORS
new file mode 100644
index 000000000..e52b72f83
--- /dev/null
+++ b/vendor/github.com/howeyc/fsnotify/AUTHORS
@@ -0,0 +1,28 @@
+# Names should be added to this file as
+# Name or Organization
+# The email address is not required for organizations.
+
+# You can update this list using the following command:
+#
+# $ git shortlog -se | awk '{print $2 " " $3 " " $4}'
+
+# Please keep the list sorted.
+
+Adrien Bustany
+Caleb Spare
+Case Nelson
+Chris Howey
+Christoffer Buchholz
+Dave Cheney
+Francisco Souza
+John C Barstow
+Kelvin Fo
+Nathan Youngman
+Paul Hammond
+Pursuit92
+Rob Figueiredo
+Travis Cline
+Tudor Golubenco
+bronze1man
+debrando
+henrikedwards
diff --git a/vendor/github.com/howeyc/fsnotify/CHANGELOG.md b/vendor/github.com/howeyc/fsnotify/CHANGELOG.md
new file mode 100644
index 000000000..761686aa9
--- /dev/null
+++ b/vendor/github.com/howeyc/fsnotify/CHANGELOG.md
@@ -0,0 +1,160 @@
+# Changelog
+
+## v0.9.0 / 2014-01-17
+
+* IsAttrib() for events that only concern a file's metadata [#79][] (thanks @abustany)
+* [Fix] kqueue: fix deadlock [#77][] (thanks @cespare)
+* [NOTICE] Development has moved to `code.google.com/p/go.exp/fsnotify` in preparation for inclusion in the Go standard library.
+
+## v0.8.12 / 2013-11-13
+
+* [API] Remove FD_SET and friends from Linux adapter
+
+## v0.8.11 / 2013-11-02
+
+* [Doc] Add Changelog [#72][] (thanks @nathany)
+* [Doc] Spotlight and double modify events on OS X [#62][] (reported by @paulhammond)
+
+## v0.8.10 / 2013-10-19
+
+* [Fix] kqueue: remove file watches when parent directory is removed [#71][] (reported by @mdwhatcott)
+* [Fix] kqueue: race between Close and readEvents [#70][] (reported by @bernerdschaefer)
+* [Doc] specify OS-specific limits in README (thanks @debrando)
+
+## v0.8.9 / 2013-09-08
+
+* [Doc] Contributing (thanks @nathany)
+* [Doc] update package path in example code [#63][] (thanks @paulhammond)
+* [Doc] GoCI badge in README (Linux only) [#60][]
+* [Doc] Cross-platform testing with Vagrant [#59][] (thanks @nathany)
+
+## v0.8.8 / 2013-06-17
+
+* [Fix] Windows: handle `ERROR_MORE_DATA` on Windows [#49][] (thanks @jbowtie)
+
+## v0.8.7 / 2013-06-03
+
+* [API] Make syscall flags internal
+* [Fix] inotify: ignore event changes
+* [Fix] race in symlink test [#45][] (reported by @srid)
+* [Fix] tests on Windows
+* lower case error messages
+
+## v0.8.6 / 2013-05-23
+
+* kqueue: Use EVT_ONLY flag on Darwin
+* [Doc] Update README with full example
+
+## v0.8.5 / 2013-05-09
+
+* [Fix] inotify: allow monitoring of "broken" symlinks (thanks @tsg)
+
+## v0.8.4 / 2013-04-07
+
+* [Fix] kqueue: watch all file events [#40][] (thanks @ChrisBuchholz)
+
+## v0.8.3 / 2013-03-13
+
+* [Fix] inoitfy/kqueue memory leak [#36][] (reported by @nbkolchin)
+* [Fix] kqueue: use fsnFlags for watching a directory [#33][] (reported by @nbkolchin)
+
+## v0.8.2 / 2013-02-07
+
+* [Doc] add Authors
+* [Fix] fix data races for map access [#29][] (thanks @fsouza)
+
+## v0.8.1 / 2013-01-09
+
+* [Fix] Windows path separators
+* [Doc] BSD License
+
+## v0.8.0 / 2012-11-09
+
+* kqueue: directory watching improvements (thanks @vmirage)
+* inotify: add `IN_MOVED_TO` [#25][] (requested by @cpisto)
+* [Fix] kqueue: deleting watched directory [#24][] (reported by @jakerr)
+
+## v0.7.4 / 2012-10-09
+
+* [Fix] inotify: fixes from https://codereview.appspot.com/5418045/ (ugorji)
+* [Fix] kqueue: preserve watch flags when watching for delete [#21][] (reported by @robfig)
+* [Fix] kqueue: watch the directory even if it isn't a new watch (thanks @robfig)
+* [Fix] kqueue: modify after recreation of file
+
+## v0.7.3 / 2012-09-27
+
+* [Fix] kqueue: watch with an existing folder inside the watched folder (thanks @vmirage)
+* [Fix] kqueue: no longer get duplicate CREATE events
+
+## v0.7.2 / 2012-09-01
+
+* kqueue: events for created directories
+
+## v0.7.1 / 2012-07-14
+
+* [Fix] for renaming files
+
+## v0.7.0 / 2012-07-02
+
+* [Feature] FSNotify flags
+* [Fix] inotify: Added file name back to event path
+
+## v0.6.0 / 2012-06-06
+
+* kqueue: watch files after directory created (thanks @tmc)
+
+## v0.5.1 / 2012-05-22
+
+* [Fix] inotify: remove all watches before Close()
+
+## v0.5.0 / 2012-05-03
+
+* [API] kqueue: return errors during watch instead of sending over channel
+* kqueue: match symlink behavior on Linux
+* inotify: add `DELETE_SELF` (requested by @taralx)
+* [Fix] kqueue: handle EINTR (reported by @robfig)
+* [Doc] Godoc example [#1][] (thanks @davecheney)
+
+## v0.4.0 / 2012-03-30
+
+* Go 1 released: build with go tool
+* [Feature] Windows support using winfsnotify
+* Windows does not have attribute change notifications
+* Roll attribute notifications into IsModify
+
+## v0.3.0 / 2012-02-19
+
+* kqueue: add files when watch directory
+
+## v0.2.0 / 2011-12-30
+
+* update to latest Go weekly code
+
+## v0.1.0 / 2011-10-19
+
+* kqueue: add watch on file creation to match inotify
+* kqueue: create file event
+* inotify: ignore `IN_IGNORED` events
+* event String()
+* linux: common FileEvent functions
+* initial commit
+
+[#79]: https://github.com/howeyc/fsnotify/pull/79
+[#77]: https://github.com/howeyc/fsnotify/pull/77
+[#72]: https://github.com/howeyc/fsnotify/issues/72
+[#71]: https://github.com/howeyc/fsnotify/issues/71
+[#70]: https://github.com/howeyc/fsnotify/issues/70
+[#63]: https://github.com/howeyc/fsnotify/issues/63
+[#62]: https://github.com/howeyc/fsnotify/issues/62
+[#60]: https://github.com/howeyc/fsnotify/issues/60
+[#59]: https://github.com/howeyc/fsnotify/issues/59
+[#49]: https://github.com/howeyc/fsnotify/issues/49
+[#45]: https://github.com/howeyc/fsnotify/issues/45
+[#40]: https://github.com/howeyc/fsnotify/issues/40
+[#36]: https://github.com/howeyc/fsnotify/issues/36
+[#33]: https://github.com/howeyc/fsnotify/issues/33
+[#29]: https://github.com/howeyc/fsnotify/issues/29
+[#25]: https://github.com/howeyc/fsnotify/issues/25
+[#24]: https://github.com/howeyc/fsnotify/issues/24
+[#21]: https://github.com/howeyc/fsnotify/issues/21
+[#1]: https://github.com/howeyc/fsnotify/issues/1
diff --git a/vendor/github.com/howeyc/fsnotify/CONTRIBUTING.md b/vendor/github.com/howeyc/fsnotify/CONTRIBUTING.md
new file mode 100644
index 000000000..b2025d72c
--- /dev/null
+++ b/vendor/github.com/howeyc/fsnotify/CONTRIBUTING.md
@@ -0,0 +1,7 @@
+# Contributing
+
+## Moving Notice
+
+There is a fork being actively developed with a new API in preparation for the Go Standard Library:
+[github.com/go-fsnotify/fsnotify](https://github.com/go-fsnotify/fsnotify)
+
diff --git a/vendor/gopkg.in.o/mgo.v2/internal/json/LICENSE b/vendor/github.com/howeyc/fsnotify/LICENSE
similarity index 96%
rename from vendor/gopkg.in.o/mgo.v2/internal/json/LICENSE
rename to vendor/github.com/howeyc/fsnotify/LICENSE
index 744875676..f21e54080 100644
--- a/vendor/gopkg.in.o/mgo.v2/internal/json/LICENSE
+++ b/vendor/github.com/howeyc/fsnotify/LICENSE
@@ -1,4 +1,5 @@
Copyright (c) 2012 The Go Authors. All rights reserved.
+Copyright (c) 2012 fsnotify Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
diff --git a/vendor/github.com/howeyc/fsnotify/README.md b/vendor/github.com/howeyc/fsnotify/README.md
new file mode 100644
index 000000000..7fdaf7c99
--- /dev/null
+++ b/vendor/github.com/howeyc/fsnotify/README.md
@@ -0,0 +1,93 @@
+# File system notifications for Go
+
+[![GoDoc](https://godoc.org/github.com/howeyc/fsnotify?status.png)](http://godoc.org/github.com/howeyc/fsnotify)
+
+Cross platform: Windows, Linux, BSD and OS X.
+
+## Moving Notice
+
+There is a fork being actively developed with a new API in preparation for the Go Standard Library:
+[github.com/go-fsnotify/fsnotify](https://github.com/go-fsnotify/fsnotify)
+
+## Example:
+
+```go
+package main
+
+import (
+ "log"
+
+ "github.com/howeyc/fsnotify"
+)
+
+func main() {
+ watcher, err := fsnotify.NewWatcher()
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ done := make(chan bool)
+
+ // Process events
+ go func() {
+ for {
+ select {
+ case ev := <-watcher.Event:
+ log.Println("event:", ev)
+ case err := <-watcher.Error:
+ log.Println("error:", err)
+ }
+ }
+ }()
+
+ err = watcher.Watch("testDir")
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ // Hang so program doesn't exit
+ <-done
+
+ /* ... do stuff ... */
+ watcher.Close()
+}
+```
+
+For each event:
+* Name
+* IsCreate()
+* IsDelete()
+* IsModify()
+* IsRename()
+
+## FAQ
+
+**When a file is moved to another directory is it still being watched?**
+
+No (it shouldn't be, unless you are watching where it was moved to).
+
+**When I watch a directory, are all subdirectories watched as well?**
+
+No, you must add watches for any directory you want to watch (a recursive watcher is in the works [#56][]).
+
+**Do I have to watch the Error and Event channels in a separate goroutine?**
+
+As of now, yes. Looking into making this single-thread friendly (see [#7][])
+
+**Why am I receiving multiple events for the same file on OS X?**
+
+Spotlight indexing on OS X can result in multiple events (see [#62][]). A temporary workaround is to add your folder(s) to the *Spotlight Privacy settings* until we have a native FSEvents implementation (see [#54][]).
+
+**How many files can be watched at once?**
+
+There are OS-specific limits as to how many watches can be created:
+* Linux: /proc/sys/fs/inotify/max_user_watches contains the limit,
+reaching this limit results in a "no space left on device" error.
+* BSD / OSX: sysctl variables "kern.maxfiles" and "kern.maxfilesperproc", reaching these limits results in a "too many open files" error.
+
+
+[#62]: https://github.com/howeyc/fsnotify/issues/62
+[#56]: https://github.com/howeyc/fsnotify/issues/56
+[#54]: https://github.com/howeyc/fsnotify/issues/54
+[#7]: https://github.com/howeyc/fsnotify/issues/7
+
diff --git a/vendor/github.com/howeyc/fsnotify/fsnotify.go b/vendor/github.com/howeyc/fsnotify/fsnotify.go
new file mode 100644
index 000000000..9a48d847d
--- /dev/null
+++ b/vendor/github.com/howeyc/fsnotify/fsnotify.go
@@ -0,0 +1,111 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package fsnotify implements file system notification.
+package fsnotify
+
+import "fmt"
+
+const (
+ FSN_CREATE = 1
+ FSN_MODIFY = 2
+ FSN_DELETE = 4
+ FSN_RENAME = 8
+
+ FSN_ALL = FSN_MODIFY | FSN_DELETE | FSN_RENAME | FSN_CREATE
+)
+
+// Purge events from interal chan to external chan if passes filter
+func (w *Watcher) purgeEvents() {
+ for ev := range w.internalEvent {
+ sendEvent := false
+ w.fsnmut.Lock()
+ fsnFlags := w.fsnFlags[ev.Name]
+ w.fsnmut.Unlock()
+
+ if (fsnFlags&FSN_CREATE == FSN_CREATE) && ev.IsCreate() {
+ sendEvent = true
+ }
+
+ if (fsnFlags&FSN_MODIFY == FSN_MODIFY) && ev.IsModify() {
+ sendEvent = true
+ }
+
+ if (fsnFlags&FSN_DELETE == FSN_DELETE) && ev.IsDelete() {
+ sendEvent = true
+ }
+
+ if (fsnFlags&FSN_RENAME == FSN_RENAME) && ev.IsRename() {
+ sendEvent = true
+ }
+
+ if sendEvent {
+ w.Event <- ev
+ }
+
+ // If there's no file, then no more events for user
+ // BSD must keep watch for internal use (watches DELETEs to keep track
+ // what files exist for create events)
+ if ev.IsDelete() {
+ w.fsnmut.Lock()
+ delete(w.fsnFlags, ev.Name)
+ w.fsnmut.Unlock()
+ }
+ }
+
+ close(w.Event)
+}
+
+// Watch a given file path
+func (w *Watcher) Watch(path string) error {
+ return w.WatchFlags(path, FSN_ALL)
+}
+
+// Watch a given file path for a particular set of notifications (FSN_MODIFY etc.)
+func (w *Watcher) WatchFlags(path string, flags uint32) error {
+ w.fsnmut.Lock()
+ w.fsnFlags[path] = flags
+ w.fsnmut.Unlock()
+ return w.watch(path)
+}
+
+// Remove a watch on a file
+func (w *Watcher) RemoveWatch(path string) error {
+ w.fsnmut.Lock()
+ delete(w.fsnFlags, path)
+ w.fsnmut.Unlock()
+ return w.removeWatch(path)
+}
+
+// String formats the event e in the form
+// "filename: DELETE|MODIFY|..."
+func (e *FileEvent) String() string {
+ var events string = ""
+
+ if e.IsCreate() {
+ events += "|" + "CREATE"
+ }
+
+ if e.IsDelete() {
+ events += "|" + "DELETE"
+ }
+
+ if e.IsModify() {
+ events += "|" + "MODIFY"
+ }
+
+ if e.IsRename() {
+ events += "|" + "RENAME"
+ }
+
+ if e.IsAttrib() {
+ events += "|" + "ATTRIB"
+ }
+
+ if len(events) > 0 {
+ events = events[1:]
+ }
+
+ return fmt.Sprintf("%q: %s", e.Name, events)
+}
diff --git a/vendor/github.com/howeyc/fsnotify/fsnotify_bsd.go b/vendor/github.com/howeyc/fsnotify/fsnotify_bsd.go
new file mode 100644
index 000000000..40c84768b
--- /dev/null
+++ b/vendor/github.com/howeyc/fsnotify/fsnotify_bsd.go
@@ -0,0 +1,496 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build freebsd openbsd netbsd dragonfly darwin
+
+package fsnotify
+
+import (
+ "errors"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "sync"
+ "syscall"
+)
+
+const (
+ // Flags (from )
+ sys_NOTE_DELETE = 0x0001 /* vnode was removed */
+ sys_NOTE_WRITE = 0x0002 /* data contents changed */
+ sys_NOTE_EXTEND = 0x0004 /* size increased */
+ sys_NOTE_ATTRIB = 0x0008 /* attributes changed */
+ sys_NOTE_LINK = 0x0010 /* link count changed */
+ sys_NOTE_RENAME = 0x0020 /* vnode was renamed */
+ sys_NOTE_REVOKE = 0x0040 /* vnode access was revoked */
+
+ // Watch all events
+ sys_NOTE_ALLEVENTS = sys_NOTE_DELETE | sys_NOTE_WRITE | sys_NOTE_ATTRIB | sys_NOTE_RENAME
+
+ // Block for 100 ms on each call to kevent
+ keventWaitTime = 100e6
+)
+
+type FileEvent struct {
+ mask uint32 // Mask of events
+ Name string // File name (optional)
+ create bool // set by fsnotify package if found new file
+}
+
+// IsCreate reports whether the FileEvent was triggered by a creation
+func (e *FileEvent) IsCreate() bool { return e.create }
+
+// IsDelete reports whether the FileEvent was triggered by a delete
+func (e *FileEvent) IsDelete() bool { return (e.mask & sys_NOTE_DELETE) == sys_NOTE_DELETE }
+
+// IsModify reports whether the FileEvent was triggered by a file modification
+func (e *FileEvent) IsModify() bool {
+ return ((e.mask&sys_NOTE_WRITE) == sys_NOTE_WRITE || (e.mask&sys_NOTE_ATTRIB) == sys_NOTE_ATTRIB)
+}
+
+// IsRename reports whether the FileEvent was triggered by a change name
+func (e *FileEvent) IsRename() bool { return (e.mask & sys_NOTE_RENAME) == sys_NOTE_RENAME }
+
+// IsAttrib reports whether the FileEvent was triggered by a change in the file metadata.
+func (e *FileEvent) IsAttrib() bool {
+ return (e.mask & sys_NOTE_ATTRIB) == sys_NOTE_ATTRIB
+}
+
+type Watcher struct {
+ mu sync.Mutex // Mutex for the Watcher itself.
+ kq int // File descriptor (as returned by the kqueue() syscall)
+ watches map[string]int // Map of watched file descriptors (key: path)
+ wmut sync.Mutex // Protects access to watches.
+ fsnFlags map[string]uint32 // Map of watched files to flags used for filter
+ fsnmut sync.Mutex // Protects access to fsnFlags.
+ enFlags map[string]uint32 // Map of watched files to evfilt note flags used in kqueue
+ enmut sync.Mutex // Protects access to enFlags.
+ paths map[int]string // Map of watched paths (key: watch descriptor)
+ finfo map[int]os.FileInfo // Map of file information (isDir, isReg; key: watch descriptor)
+ pmut sync.Mutex // Protects access to paths and finfo.
+ fileExists map[string]bool // Keep track of if we know this file exists (to stop duplicate create events)
+ femut sync.Mutex // Protects access to fileExists.
+ externalWatches map[string]bool // Map of watches added by user of the library.
+ ewmut sync.Mutex // Protects access to externalWatches.
+ Error chan error // Errors are sent on this channel
+ internalEvent chan *FileEvent // Events are queued on this channel
+ Event chan *FileEvent // Events are returned on this channel
+ done chan bool // Channel for sending a "quit message" to the reader goroutine
+ isClosed bool // Set to true when Close() is first called
+}
+
+// NewWatcher creates and returns a new kevent instance using kqueue(2)
+func NewWatcher() (*Watcher, error) {
+ fd, errno := syscall.Kqueue()
+ if fd == -1 {
+ return nil, os.NewSyscallError("kqueue", errno)
+ }
+ w := &Watcher{
+ kq: fd,
+ watches: make(map[string]int),
+ fsnFlags: make(map[string]uint32),
+ enFlags: make(map[string]uint32),
+ paths: make(map[int]string),
+ finfo: make(map[int]os.FileInfo),
+ fileExists: make(map[string]bool),
+ externalWatches: make(map[string]bool),
+ internalEvent: make(chan *FileEvent),
+ Event: make(chan *FileEvent),
+ Error: make(chan error),
+ done: make(chan bool, 1),
+ }
+
+ go w.readEvents()
+ go w.purgeEvents()
+ return w, nil
+}
+
+// Close closes a kevent watcher instance
+// It sends a message to the reader goroutine to quit and removes all watches
+// associated with the kevent instance
+func (w *Watcher) Close() error {
+ w.mu.Lock()
+ if w.isClosed {
+ w.mu.Unlock()
+ return nil
+ }
+ w.isClosed = true
+ w.mu.Unlock()
+
+ // Send "quit" message to the reader goroutine
+ w.done <- true
+ w.wmut.Lock()
+ ws := w.watches
+ w.wmut.Unlock()
+ for path := range ws {
+ w.removeWatch(path)
+ }
+
+ return nil
+}
+
+// AddWatch adds path to the watched file set.
+// The flags are interpreted as described in kevent(2).
+func (w *Watcher) addWatch(path string, flags uint32) error {
+ w.mu.Lock()
+ if w.isClosed {
+ w.mu.Unlock()
+ return errors.New("kevent instance already closed")
+ }
+ w.mu.Unlock()
+
+ watchDir := false
+
+ w.wmut.Lock()
+ watchfd, found := w.watches[path]
+ w.wmut.Unlock()
+ if !found {
+ fi, errstat := os.Lstat(path)
+ if errstat != nil {
+ return errstat
+ }
+
+ // don't watch socket
+ if fi.Mode()&os.ModeSocket == os.ModeSocket {
+ return nil
+ }
+
+ // Follow Symlinks
+ // Unfortunately, Linux can add bogus symlinks to watch list without
+ // issue, and Windows can't do symlinks period (AFAIK). To maintain
+ // consistency, we will act like everything is fine. There will simply
+ // be no file events for broken symlinks.
+ // Hence the returns of nil on errors.
+ if fi.Mode()&os.ModeSymlink == os.ModeSymlink {
+ path, err := filepath.EvalSymlinks(path)
+ if err != nil {
+ return nil
+ }
+
+ fi, errstat = os.Lstat(path)
+ if errstat != nil {
+ return nil
+ }
+ }
+
+ fd, errno := syscall.Open(path, open_FLAGS, 0700)
+ if fd == -1 {
+ return errno
+ }
+ watchfd = fd
+
+ w.wmut.Lock()
+ w.watches[path] = watchfd
+ w.wmut.Unlock()
+
+ w.pmut.Lock()
+ w.paths[watchfd] = path
+ w.finfo[watchfd] = fi
+ w.pmut.Unlock()
+ }
+ // Watch the directory if it has not been watched before.
+ w.pmut.Lock()
+ w.enmut.Lock()
+ if w.finfo[watchfd].IsDir() &&
+ (flags&sys_NOTE_WRITE) == sys_NOTE_WRITE &&
+ (!found || (w.enFlags[path]&sys_NOTE_WRITE) != sys_NOTE_WRITE) {
+ watchDir = true
+ }
+ w.enmut.Unlock()
+ w.pmut.Unlock()
+
+ w.enmut.Lock()
+ w.enFlags[path] = flags
+ w.enmut.Unlock()
+
+ var kbuf [1]syscall.Kevent_t
+ watchEntry := &kbuf[0]
+ watchEntry.Fflags = flags
+ syscall.SetKevent(watchEntry, watchfd, syscall.EVFILT_VNODE, syscall.EV_ADD|syscall.EV_CLEAR)
+ entryFlags := watchEntry.Flags
+ success, errno := syscall.Kevent(w.kq, kbuf[:], nil, nil)
+ if success == -1 {
+ return errno
+ } else if (entryFlags & syscall.EV_ERROR) == syscall.EV_ERROR {
+ return errors.New("kevent add error")
+ }
+
+ if watchDir {
+ errdir := w.watchDirectoryFiles(path)
+ if errdir != nil {
+ return errdir
+ }
+ }
+ return nil
+}
+
+// Watch adds path to the watched file set, watching all events.
+func (w *Watcher) watch(path string) error {
+ w.ewmut.Lock()
+ w.externalWatches[path] = true
+ w.ewmut.Unlock()
+ return w.addWatch(path, sys_NOTE_ALLEVENTS)
+}
+
+// RemoveWatch removes path from the watched file set.
+func (w *Watcher) removeWatch(path string) error {
+ w.wmut.Lock()
+ watchfd, ok := w.watches[path]
+ w.wmut.Unlock()
+ if !ok {
+ return errors.New(fmt.Sprintf("can't remove non-existent kevent watch for: %s", path))
+ }
+ var kbuf [1]syscall.Kevent_t
+ watchEntry := &kbuf[0]
+ syscall.SetKevent(watchEntry, watchfd, syscall.EVFILT_VNODE, syscall.EV_DELETE)
+ entryFlags := watchEntry.Flags
+ success, errno := syscall.Kevent(w.kq, kbuf[:], nil, nil)
+ if success == -1 {
+ return os.NewSyscallError("kevent_rm_watch", errno)
+ } else if (entryFlags & syscall.EV_ERROR) == syscall.EV_ERROR {
+ return errors.New("kevent rm error")
+ }
+ syscall.Close(watchfd)
+ w.wmut.Lock()
+ delete(w.watches, path)
+ w.wmut.Unlock()
+ w.enmut.Lock()
+ delete(w.enFlags, path)
+ w.enmut.Unlock()
+ w.pmut.Lock()
+ delete(w.paths, watchfd)
+ fInfo := w.finfo[watchfd]
+ delete(w.finfo, watchfd)
+ w.pmut.Unlock()
+
+ // Find all watched paths that are in this directory that are not external.
+ if fInfo.IsDir() {
+ var pathsToRemove []string
+ w.pmut.Lock()
+ for _, wpath := range w.paths {
+ wdir, _ := filepath.Split(wpath)
+ if filepath.Clean(wdir) == filepath.Clean(path) {
+ w.ewmut.Lock()
+ if !w.externalWatches[wpath] {
+ pathsToRemove = append(pathsToRemove, wpath)
+ }
+ w.ewmut.Unlock()
+ }
+ }
+ w.pmut.Unlock()
+ for _, p := range pathsToRemove {
+ // Since these are internal, not much sense in propagating error
+ // to the user, as that will just confuse them with an error about
+ // a path they did not explicitly watch themselves.
+ w.removeWatch(p)
+ }
+ }
+
+ return nil
+}
+
+// readEvents reads from the kqueue file descriptor, converts the
+// received events into Event objects and sends them via the Event channel
+func (w *Watcher) readEvents() {
+ var (
+ eventbuf [10]syscall.Kevent_t // Event buffer
+ events []syscall.Kevent_t // Received events
+ twait *syscall.Timespec // Time to block waiting for events
+ n int // Number of events returned from kevent
+ errno error // Syscall errno
+ )
+ events = eventbuf[0:0]
+ twait = new(syscall.Timespec)
+ *twait = syscall.NsecToTimespec(keventWaitTime)
+
+ for {
+ // See if there is a message on the "done" channel
+ var done bool
+ select {
+ case done = <-w.done:
+ default:
+ }
+
+ // If "done" message is received
+ if done {
+ errno := syscall.Close(w.kq)
+ if errno != nil {
+ w.Error <- os.NewSyscallError("close", errno)
+ }
+ close(w.internalEvent)
+ close(w.Error)
+ return
+ }
+
+ // Get new events
+ if len(events) == 0 {
+ n, errno = syscall.Kevent(w.kq, nil, eventbuf[:], twait)
+
+ // EINTR is okay, basically the syscall was interrupted before
+ // timeout expired.
+ if errno != nil && errno != syscall.EINTR {
+ w.Error <- os.NewSyscallError("kevent", errno)
+ continue
+ }
+
+ // Received some events
+ if n > 0 {
+ events = eventbuf[0:n]
+ }
+ }
+
+ // Flush the events we received to the events channel
+ for len(events) > 0 {
+ fileEvent := new(FileEvent)
+ watchEvent := &events[0]
+ fileEvent.mask = uint32(watchEvent.Fflags)
+ w.pmut.Lock()
+ fileEvent.Name = w.paths[int(watchEvent.Ident)]
+ fileInfo := w.finfo[int(watchEvent.Ident)]
+ w.pmut.Unlock()
+ if fileInfo != nil && fileInfo.IsDir() && !fileEvent.IsDelete() {
+ // Double check to make sure the directory exist. This can happen when
+ // we do a rm -fr on a recursively watched folders and we receive a
+ // modification event first but the folder has been deleted and later
+ // receive the delete event
+ if _, err := os.Lstat(fileEvent.Name); os.IsNotExist(err) {
+ // mark is as delete event
+ fileEvent.mask |= sys_NOTE_DELETE
+ }
+ }
+
+ if fileInfo != nil && fileInfo.IsDir() && fileEvent.IsModify() && !fileEvent.IsDelete() {
+ w.sendDirectoryChangeEvents(fileEvent.Name)
+ } else {
+ // Send the event on the events channel
+ w.internalEvent <- fileEvent
+ }
+
+ // Move to next event
+ events = events[1:]
+
+ if fileEvent.IsRename() {
+ w.removeWatch(fileEvent.Name)
+ w.femut.Lock()
+ delete(w.fileExists, fileEvent.Name)
+ w.femut.Unlock()
+ }
+ if fileEvent.IsDelete() {
+ w.removeWatch(fileEvent.Name)
+ w.femut.Lock()
+ delete(w.fileExists, fileEvent.Name)
+ w.femut.Unlock()
+
+ // Look for a file that may have overwritten this
+ // (ie mv f1 f2 will delete f2 then create f2)
+ fileDir, _ := filepath.Split(fileEvent.Name)
+ fileDir = filepath.Clean(fileDir)
+ w.wmut.Lock()
+ _, found := w.watches[fileDir]
+ w.wmut.Unlock()
+ if found {
+ // make sure the directory exist before we watch for changes. When we
+ // do a recursive watch and perform rm -fr, the parent directory might
+ // have gone missing, ignore the missing directory and let the
+ // upcoming delete event remove the watch form the parent folder
+ if _, err := os.Lstat(fileDir); !os.IsNotExist(err) {
+ w.sendDirectoryChangeEvents(fileDir)
+ }
+ }
+ }
+ }
+ }
+}
+
+func (w *Watcher) watchDirectoryFiles(dirPath string) error {
+ // Get all files
+ files, err := ioutil.ReadDir(dirPath)
+ if err != nil {
+ return err
+ }
+
+ // Search for new files
+ for _, fileInfo := range files {
+ filePath := filepath.Join(dirPath, fileInfo.Name())
+
+ // Inherit fsnFlags from parent directory
+ w.fsnmut.Lock()
+ if flags, found := w.fsnFlags[dirPath]; found {
+ w.fsnFlags[filePath] = flags
+ } else {
+ w.fsnFlags[filePath] = FSN_ALL
+ }
+ w.fsnmut.Unlock()
+
+ if fileInfo.IsDir() == false {
+ // Watch file to mimic linux fsnotify
+ e := w.addWatch(filePath, sys_NOTE_ALLEVENTS)
+ if e != nil {
+ return e
+ }
+ } else {
+ // If the user is currently watching directory
+ // we want to preserve the flags used
+ w.enmut.Lock()
+ currFlags, found := w.enFlags[filePath]
+ w.enmut.Unlock()
+ var newFlags uint32 = sys_NOTE_DELETE
+ if found {
+ newFlags |= currFlags
+ }
+
+ // Linux gives deletes if not explicitly watching
+ e := w.addWatch(filePath, newFlags)
+ if e != nil {
+ return e
+ }
+ }
+ w.femut.Lock()
+ w.fileExists[filePath] = true
+ w.femut.Unlock()
+ }
+
+ return nil
+}
+
+// sendDirectoryEvents searches the directory for newly created files
+// and sends them over the event channel. This functionality is to have
+// the BSD version of fsnotify match linux fsnotify which provides a
+// create event for files created in a watched directory.
+func (w *Watcher) sendDirectoryChangeEvents(dirPath string) {
+ // Get all files
+ files, err := ioutil.ReadDir(dirPath)
+ if err != nil {
+ w.Error <- err
+ }
+
+ // Search for new files
+ for _, fileInfo := range files {
+ filePath := filepath.Join(dirPath, fileInfo.Name())
+ w.femut.Lock()
+ _, doesExist := w.fileExists[filePath]
+ w.femut.Unlock()
+ if !doesExist {
+ // Inherit fsnFlags from parent directory
+ w.fsnmut.Lock()
+ if flags, found := w.fsnFlags[dirPath]; found {
+ w.fsnFlags[filePath] = flags
+ } else {
+ w.fsnFlags[filePath] = FSN_ALL
+ }
+ w.fsnmut.Unlock()
+
+ // Send create event
+ fileEvent := new(FileEvent)
+ fileEvent.Name = filePath
+ fileEvent.create = true
+ w.internalEvent <- fileEvent
+ }
+ w.femut.Lock()
+ w.fileExists[filePath] = true
+ w.femut.Unlock()
+ }
+ w.watchDirectoryFiles(dirPath)
+}
diff --git a/vendor/github.com/howeyc/fsnotify/fsnotify_linux.go b/vendor/github.com/howeyc/fsnotify/fsnotify_linux.go
new file mode 100644
index 000000000..80ade879f
--- /dev/null
+++ b/vendor/github.com/howeyc/fsnotify/fsnotify_linux.go
@@ -0,0 +1,304 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux
+
+package fsnotify
+
+import (
+ "errors"
+ "fmt"
+ "os"
+ "strings"
+ "sync"
+ "syscall"
+ "unsafe"
+)
+
+const (
+ // Options for inotify_init() are not exported
+ // sys_IN_CLOEXEC uint32 = syscall.IN_CLOEXEC
+ // sys_IN_NONBLOCK uint32 = syscall.IN_NONBLOCK
+
+ // Options for AddWatch
+ sys_IN_DONT_FOLLOW uint32 = syscall.IN_DONT_FOLLOW
+ sys_IN_ONESHOT uint32 = syscall.IN_ONESHOT
+ sys_IN_ONLYDIR uint32 = syscall.IN_ONLYDIR
+
+ // The "sys_IN_MASK_ADD" option is not exported, as AddWatch
+ // adds it automatically, if there is already a watch for the given path
+ // sys_IN_MASK_ADD uint32 = syscall.IN_MASK_ADD
+
+ // Events
+ sys_IN_ACCESS uint32 = syscall.IN_ACCESS
+ sys_IN_ALL_EVENTS uint32 = syscall.IN_ALL_EVENTS
+ sys_IN_ATTRIB uint32 = syscall.IN_ATTRIB
+ sys_IN_CLOSE uint32 = syscall.IN_CLOSE
+ sys_IN_CLOSE_NOWRITE uint32 = syscall.IN_CLOSE_NOWRITE
+ sys_IN_CLOSE_WRITE uint32 = syscall.IN_CLOSE_WRITE
+ sys_IN_CREATE uint32 = syscall.IN_CREATE
+ sys_IN_DELETE uint32 = syscall.IN_DELETE
+ sys_IN_DELETE_SELF uint32 = syscall.IN_DELETE_SELF
+ sys_IN_MODIFY uint32 = syscall.IN_MODIFY
+ sys_IN_MOVE uint32 = syscall.IN_MOVE
+ sys_IN_MOVED_FROM uint32 = syscall.IN_MOVED_FROM
+ sys_IN_MOVED_TO uint32 = syscall.IN_MOVED_TO
+ sys_IN_MOVE_SELF uint32 = syscall.IN_MOVE_SELF
+ sys_IN_OPEN uint32 = syscall.IN_OPEN
+
+ sys_AGNOSTIC_EVENTS = sys_IN_MOVED_TO | sys_IN_MOVED_FROM | sys_IN_CREATE | sys_IN_ATTRIB | sys_IN_MODIFY | sys_IN_MOVE_SELF | sys_IN_DELETE | sys_IN_DELETE_SELF
+
+ // Special events
+ sys_IN_ISDIR uint32 = syscall.IN_ISDIR
+ sys_IN_IGNORED uint32 = syscall.IN_IGNORED
+ sys_IN_Q_OVERFLOW uint32 = syscall.IN_Q_OVERFLOW
+ sys_IN_UNMOUNT uint32 = syscall.IN_UNMOUNT
+)
+
+type FileEvent struct {
+ mask uint32 // Mask of events
+ cookie uint32 // Unique cookie associating related events (for rename(2))
+ Name string // File name (optional)
+}
+
+// IsCreate reports whether the FileEvent was triggered by a creation
+func (e *FileEvent) IsCreate() bool {
+ return (e.mask&sys_IN_CREATE) == sys_IN_CREATE || (e.mask&sys_IN_MOVED_TO) == sys_IN_MOVED_TO
+}
+
+// IsDelete reports whether the FileEvent was triggered by a delete
+func (e *FileEvent) IsDelete() bool {
+ return (e.mask&sys_IN_DELETE_SELF) == sys_IN_DELETE_SELF || (e.mask&sys_IN_DELETE) == sys_IN_DELETE
+}
+
+// IsModify reports whether the FileEvent was triggered by a file modification or attribute change
+func (e *FileEvent) IsModify() bool {
+ return ((e.mask&sys_IN_MODIFY) == sys_IN_MODIFY || (e.mask&sys_IN_ATTRIB) == sys_IN_ATTRIB)
+}
+
+// IsRename reports whether the FileEvent was triggered by a change name
+func (e *FileEvent) IsRename() bool {
+ return ((e.mask&sys_IN_MOVE_SELF) == sys_IN_MOVE_SELF || (e.mask&sys_IN_MOVED_FROM) == sys_IN_MOVED_FROM)
+}
+
+// IsAttrib reports whether the FileEvent was triggered by a change in the file metadata.
+func (e *FileEvent) IsAttrib() bool {
+ return (e.mask & sys_IN_ATTRIB) == sys_IN_ATTRIB
+}
+
+type watch struct {
+ wd uint32 // Watch descriptor (as returned by the inotify_add_watch() syscall)
+ flags uint32 // inotify flags of this watch (see inotify(7) for the list of valid flags)
+}
+
+type Watcher struct {
+ mu sync.Mutex // Map access
+ fd int // File descriptor (as returned by the inotify_init() syscall)
+ watches map[string]*watch // Map of inotify watches (key: path)
+ fsnFlags map[string]uint32 // Map of watched files to flags used for filter
+ fsnmut sync.Mutex // Protects access to fsnFlags.
+ paths map[int]string // Map of watched paths (key: watch descriptor)
+ Error chan error // Errors are sent on this channel
+ internalEvent chan *FileEvent // Events are queued on this channel
+ Event chan *FileEvent // Events are returned on this channel
+ done chan bool // Channel for sending a "quit message" to the reader goroutine
+ isClosed bool // Set to true when Close() is first called
+}
+
+// NewWatcher creates and returns a new inotify instance using inotify_init(2)
+func NewWatcher() (*Watcher, error) {
+ fd, errno := syscall.InotifyInit()
+ if fd == -1 {
+ return nil, os.NewSyscallError("inotify_init", errno)
+ }
+ w := &Watcher{
+ fd: fd,
+ watches: make(map[string]*watch),
+ fsnFlags: make(map[string]uint32),
+ paths: make(map[int]string),
+ internalEvent: make(chan *FileEvent),
+ Event: make(chan *FileEvent),
+ Error: make(chan error),
+ done: make(chan bool, 1),
+ }
+
+ go w.readEvents()
+ go w.purgeEvents()
+ return w, nil
+}
+
+// Close closes an inotify watcher instance
+// It sends a message to the reader goroutine to quit and removes all watches
+// associated with the inotify instance
+func (w *Watcher) Close() error {
+ if w.isClosed {
+ return nil
+ }
+ w.isClosed = true
+
+ // Remove all watches
+ for path := range w.watches {
+ w.RemoveWatch(path)
+ }
+
+ // Send "quit" message to the reader goroutine
+ w.done <- true
+
+ return nil
+}
+
+// AddWatch adds path to the watched file set.
+// The flags are interpreted as described in inotify_add_watch(2).
+func (w *Watcher) addWatch(path string, flags uint32) error {
+ if w.isClosed {
+ return errors.New("inotify instance already closed")
+ }
+
+ w.mu.Lock()
+ watchEntry, found := w.watches[path]
+ w.mu.Unlock()
+ if found {
+ watchEntry.flags |= flags
+ flags |= syscall.IN_MASK_ADD
+ }
+ wd, errno := syscall.InotifyAddWatch(w.fd, path, flags)
+ if wd == -1 {
+ return errno
+ }
+
+ w.mu.Lock()
+ w.watches[path] = &watch{wd: uint32(wd), flags: flags}
+ w.paths[wd] = path
+ w.mu.Unlock()
+
+ return nil
+}
+
+// Watch adds path to the watched file set, watching all events.
+func (w *Watcher) watch(path string) error {
+ return w.addWatch(path, sys_AGNOSTIC_EVENTS)
+}
+
+// RemoveWatch removes path from the watched file set.
+func (w *Watcher) removeWatch(path string) error {
+ w.mu.Lock()
+ defer w.mu.Unlock()
+ watch, ok := w.watches[path]
+ if !ok {
+ return errors.New(fmt.Sprintf("can't remove non-existent inotify watch for: %s", path))
+ }
+ success, errno := syscall.InotifyRmWatch(w.fd, watch.wd)
+ if success == -1 {
+ return os.NewSyscallError("inotify_rm_watch", errno)
+ }
+ delete(w.watches, path)
+ return nil
+}
+
+// readEvents reads from the inotify file descriptor, converts the
+// received events into Event objects and sends them via the Event channel
+func (w *Watcher) readEvents() {
+ var (
+ buf [syscall.SizeofInotifyEvent * 4096]byte // Buffer for a maximum of 4096 raw events
+ n int // Number of bytes read with read()
+ errno error // Syscall errno
+ )
+
+ for {
+ // See if there is a message on the "done" channel
+ select {
+ case <-w.done:
+ syscall.Close(w.fd)
+ close(w.internalEvent)
+ close(w.Error)
+ return
+ default:
+ }
+
+ n, errno = syscall.Read(w.fd, buf[:])
+
+ // If EOF is received
+ if n == 0 {
+ syscall.Close(w.fd)
+ close(w.internalEvent)
+ close(w.Error)
+ return
+ }
+
+ if n < 0 {
+ w.Error <- os.NewSyscallError("read", errno)
+ continue
+ }
+ if n < syscall.SizeofInotifyEvent {
+ w.Error <- errors.New("inotify: short read in readEvents()")
+ continue
+ }
+
+ var offset uint32 = 0
+ // We don't know how many events we just read into the buffer
+ // While the offset points to at least one whole event...
+ for offset <= uint32(n-syscall.SizeofInotifyEvent) {
+ // Point "raw" to the event in the buffer
+ raw := (*syscall.InotifyEvent)(unsafe.Pointer(&buf[offset]))
+ event := new(FileEvent)
+ event.mask = uint32(raw.Mask)
+ event.cookie = uint32(raw.Cookie)
+ nameLen := uint32(raw.Len)
+ // If the event happened to the watched directory or the watched file, the kernel
+ // doesn't append the filename to the event, but we would like to always fill the
+ // the "Name" field with a valid filename. We retrieve the path of the watch from
+ // the "paths" map.
+ w.mu.Lock()
+ event.Name = w.paths[int(raw.Wd)]
+ w.mu.Unlock()
+ watchedName := event.Name
+ if nameLen > 0 {
+ // Point "bytes" at the first byte of the filename
+ bytes := (*[syscall.PathMax]byte)(unsafe.Pointer(&buf[offset+syscall.SizeofInotifyEvent]))
+ // The filename is padded with NUL bytes. TrimRight() gets rid of those.
+ event.Name += "/" + strings.TrimRight(string(bytes[0:nameLen]), "\000")
+ }
+
+ // Send the events that are not ignored on the events channel
+ if !event.ignoreLinux() {
+ // Setup FSNotify flags (inherit from directory watch)
+ w.fsnmut.Lock()
+ if _, fsnFound := w.fsnFlags[event.Name]; !fsnFound {
+ if fsnFlags, watchFound := w.fsnFlags[watchedName]; watchFound {
+ w.fsnFlags[event.Name] = fsnFlags
+ } else {
+ w.fsnFlags[event.Name] = FSN_ALL
+ }
+ }
+ w.fsnmut.Unlock()
+
+ w.internalEvent <- event
+ }
+
+ // Move to the next event in the buffer
+ offset += syscall.SizeofInotifyEvent + nameLen
+ }
+ }
+}
+
+// Certain types of events can be "ignored" and not sent over the Event
+// channel. Such as events marked ignore by the kernel, or MODIFY events
+// against files that do not exist.
+func (e *FileEvent) ignoreLinux() bool {
+ // Ignore anything the inotify API says to ignore
+ if e.mask&sys_IN_IGNORED == sys_IN_IGNORED {
+ return true
+ }
+
+ // If the event is not a DELETE or RENAME, the file must exist.
+ // Otherwise the event is ignored.
+ // *Note*: this was put in place because it was seen that a MODIFY
+ // event was sent after the DELETE. This ignores that MODIFY and
+ // assumes a DELETE will come or has come if the file doesn't exist.
+ if !(e.IsDelete() || e.IsRename()) {
+ _, statErr := os.Lstat(e.Name)
+ return os.IsNotExist(statErr)
+ }
+ return false
+}
diff --git a/vendor/github.com/howeyc/fsnotify/fsnotify_open_bsd.go b/vendor/github.com/howeyc/fsnotify/fsnotify_open_bsd.go
new file mode 100644
index 000000000..f728a6ffd
--- /dev/null
+++ b/vendor/github.com/howeyc/fsnotify/fsnotify_open_bsd.go
@@ -0,0 +1,11 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build freebsd openbsd netbsd dragonfly
+
+package fsnotify
+
+import "syscall"
+
+const open_FLAGS = syscall.O_NONBLOCK | syscall.O_RDONLY
diff --git a/vendor/github.com/howeyc/fsnotify/fsnotify_open_darwin.go b/vendor/github.com/howeyc/fsnotify/fsnotify_open_darwin.go
new file mode 100644
index 000000000..d450318e6
--- /dev/null
+++ b/vendor/github.com/howeyc/fsnotify/fsnotify_open_darwin.go
@@ -0,0 +1,11 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin
+
+package fsnotify
+
+import "syscall"
+
+const open_FLAGS = syscall.O_EVTONLY
diff --git a/vendor/github.com/howeyc/fsnotify/fsnotify_windows.go b/vendor/github.com/howeyc/fsnotify/fsnotify_windows.go
new file mode 100644
index 000000000..d88ae6340
--- /dev/null
+++ b/vendor/github.com/howeyc/fsnotify/fsnotify_windows.go
@@ -0,0 +1,598 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build windows
+
+package fsnotify
+
+import (
+ "errors"
+ "fmt"
+ "os"
+ "path/filepath"
+ "runtime"
+ "sync"
+ "syscall"
+ "unsafe"
+)
+
+const (
+ // Options for AddWatch
+ sys_FS_ONESHOT = 0x80000000
+ sys_FS_ONLYDIR = 0x1000000
+
+ // Events
+ sys_FS_ACCESS = 0x1
+ sys_FS_ALL_EVENTS = 0xfff
+ sys_FS_ATTRIB = 0x4
+ sys_FS_CLOSE = 0x18
+ sys_FS_CREATE = 0x100
+ sys_FS_DELETE = 0x200
+ sys_FS_DELETE_SELF = 0x400
+ sys_FS_MODIFY = 0x2
+ sys_FS_MOVE = 0xc0
+ sys_FS_MOVED_FROM = 0x40
+ sys_FS_MOVED_TO = 0x80
+ sys_FS_MOVE_SELF = 0x800
+
+ // Special events
+ sys_FS_IGNORED = 0x8000
+ sys_FS_Q_OVERFLOW = 0x4000
+)
+
+const (
+ // TODO(nj): Use syscall.ERROR_MORE_DATA from ztypes_windows in Go 1.3+
+ sys_ERROR_MORE_DATA syscall.Errno = 234
+)
+
+// Event is the type of the notification messages
+// received on the watcher's Event channel.
+type FileEvent struct {
+ mask uint32 // Mask of events
+ cookie uint32 // Unique cookie associating related events (for rename)
+ Name string // File name (optional)
+}
+
+// IsCreate reports whether the FileEvent was triggered by a creation
+func (e *FileEvent) IsCreate() bool { return (e.mask & sys_FS_CREATE) == sys_FS_CREATE }
+
+// IsDelete reports whether the FileEvent was triggered by a delete
+func (e *FileEvent) IsDelete() bool {
+ return ((e.mask&sys_FS_DELETE) == sys_FS_DELETE || (e.mask&sys_FS_DELETE_SELF) == sys_FS_DELETE_SELF)
+}
+
+// IsModify reports whether the FileEvent was triggered by a file modification or attribute change
+func (e *FileEvent) IsModify() bool {
+ return ((e.mask&sys_FS_MODIFY) == sys_FS_MODIFY || (e.mask&sys_FS_ATTRIB) == sys_FS_ATTRIB)
+}
+
+// IsRename reports whether the FileEvent was triggered by a change name
+func (e *FileEvent) IsRename() bool {
+ return ((e.mask&sys_FS_MOVE) == sys_FS_MOVE || (e.mask&sys_FS_MOVE_SELF) == sys_FS_MOVE_SELF || (e.mask&sys_FS_MOVED_FROM) == sys_FS_MOVED_FROM || (e.mask&sys_FS_MOVED_TO) == sys_FS_MOVED_TO)
+}
+
+// IsAttrib reports whether the FileEvent was triggered by a change in the file metadata.
+func (e *FileEvent) IsAttrib() bool {
+ return (e.mask & sys_FS_ATTRIB) == sys_FS_ATTRIB
+}
+
+const (
+ opAddWatch = iota
+ opRemoveWatch
+)
+
+const (
+ provisional uint64 = 1 << (32 + iota)
+)
+
+type input struct {
+ op int
+ path string
+ flags uint32
+ reply chan error
+}
+
+type inode struct {
+ handle syscall.Handle
+ volume uint32
+ index uint64
+}
+
+type watch struct {
+ ov syscall.Overlapped
+ ino *inode // i-number
+ path string // Directory path
+ mask uint64 // Directory itself is being watched with these notify flags
+ names map[string]uint64 // Map of names being watched and their notify flags
+ rename string // Remembers the old name while renaming a file
+ buf [4096]byte
+}
+
+type indexMap map[uint64]*watch
+type watchMap map[uint32]indexMap
+
+// A Watcher waits for and receives event notifications
+// for a specific set of files and directories.
+type Watcher struct {
+ mu sync.Mutex // Map access
+ port syscall.Handle // Handle to completion port
+ watches watchMap // Map of watches (key: i-number)
+ fsnFlags map[string]uint32 // Map of watched files to flags used for filter
+ fsnmut sync.Mutex // Protects access to fsnFlags.
+ input chan *input // Inputs to the reader are sent on this channel
+ internalEvent chan *FileEvent // Events are queued on this channel
+ Event chan *FileEvent // Events are returned on this channel
+ Error chan error // Errors are sent on this channel
+ isClosed bool // Set to true when Close() is first called
+ quit chan chan<- error
+ cookie uint32
+}
+
+// NewWatcher creates and returns a Watcher.
+func NewWatcher() (*Watcher, error) {
+ port, e := syscall.CreateIoCompletionPort(syscall.InvalidHandle, 0, 0, 0)
+ if e != nil {
+ return nil, os.NewSyscallError("CreateIoCompletionPort", e)
+ }
+ w := &Watcher{
+ port: port,
+ watches: make(watchMap),
+ fsnFlags: make(map[string]uint32),
+ input: make(chan *input, 1),
+ Event: make(chan *FileEvent, 50),
+ internalEvent: make(chan *FileEvent),
+ Error: make(chan error),
+ quit: make(chan chan<- error, 1),
+ }
+ go w.readEvents()
+ go w.purgeEvents()
+ return w, nil
+}
+
+// Close closes a Watcher.
+// It sends a message to the reader goroutine to quit and removes all watches
+// associated with the watcher.
+func (w *Watcher) Close() error {
+ if w.isClosed {
+ return nil
+ }
+ w.isClosed = true
+
+ // Send "quit" message to the reader goroutine
+ ch := make(chan error)
+ w.quit <- ch
+ if err := w.wakeupReader(); err != nil {
+ return err
+ }
+ return <-ch
+}
+
+// AddWatch adds path to the watched file set.
+func (w *Watcher) AddWatch(path string, flags uint32) error {
+ if w.isClosed {
+ return errors.New("watcher already closed")
+ }
+ in := &input{
+ op: opAddWatch,
+ path: filepath.Clean(path),
+ flags: flags,
+ reply: make(chan error),
+ }
+ w.input <- in
+ if err := w.wakeupReader(); err != nil {
+ return err
+ }
+ return <-in.reply
+}
+
+// Watch adds path to the watched file set, watching all events.
+func (w *Watcher) watch(path string) error {
+ return w.AddWatch(path, sys_FS_ALL_EVENTS)
+}
+
+// RemoveWatch removes path from the watched file set.
+func (w *Watcher) removeWatch(path string) error {
+ in := &input{
+ op: opRemoveWatch,
+ path: filepath.Clean(path),
+ reply: make(chan error),
+ }
+ w.input <- in
+ if err := w.wakeupReader(); err != nil {
+ return err
+ }
+ return <-in.reply
+}
+
+func (w *Watcher) wakeupReader() error {
+ e := syscall.PostQueuedCompletionStatus(w.port, 0, 0, nil)
+ if e != nil {
+ return os.NewSyscallError("PostQueuedCompletionStatus", e)
+ }
+ return nil
+}
+
+func getDir(pathname string) (dir string, err error) {
+ attr, e := syscall.GetFileAttributes(syscall.StringToUTF16Ptr(pathname))
+ if e != nil {
+ return "", os.NewSyscallError("GetFileAttributes", e)
+ }
+ if attr&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 {
+ dir = pathname
+ } else {
+ dir, _ = filepath.Split(pathname)
+ dir = filepath.Clean(dir)
+ }
+ return
+}
+
+func getIno(path string) (ino *inode, err error) {
+ h, e := syscall.CreateFile(syscall.StringToUTF16Ptr(path),
+ syscall.FILE_LIST_DIRECTORY,
+ syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE,
+ nil, syscall.OPEN_EXISTING,
+ syscall.FILE_FLAG_BACKUP_SEMANTICS|syscall.FILE_FLAG_OVERLAPPED, 0)
+ if e != nil {
+ return nil, os.NewSyscallError("CreateFile", e)
+ }
+ var fi syscall.ByHandleFileInformation
+ if e = syscall.GetFileInformationByHandle(h, &fi); e != nil {
+ syscall.CloseHandle(h)
+ return nil, os.NewSyscallError("GetFileInformationByHandle", e)
+ }
+ ino = &inode{
+ handle: h,
+ volume: fi.VolumeSerialNumber,
+ index: uint64(fi.FileIndexHigh)<<32 | uint64(fi.FileIndexLow),
+ }
+ return ino, nil
+}
+
+// Must run within the I/O thread.
+func (m watchMap) get(ino *inode) *watch {
+ if i := m[ino.volume]; i != nil {
+ return i[ino.index]
+ }
+ return nil
+}
+
+// Must run within the I/O thread.
+func (m watchMap) set(ino *inode, watch *watch) {
+ i := m[ino.volume]
+ if i == nil {
+ i = make(indexMap)
+ m[ino.volume] = i
+ }
+ i[ino.index] = watch
+}
+
+// Must run within the I/O thread.
+func (w *Watcher) addWatch(pathname string, flags uint64) error {
+ dir, err := getDir(pathname)
+ if err != nil {
+ return err
+ }
+ if flags&sys_FS_ONLYDIR != 0 && pathname != dir {
+ return nil
+ }
+ ino, err := getIno(dir)
+ if err != nil {
+ return err
+ }
+ w.mu.Lock()
+ watchEntry := w.watches.get(ino)
+ w.mu.Unlock()
+ if watchEntry == nil {
+ if _, e := syscall.CreateIoCompletionPort(ino.handle, w.port, 0, 0); e != nil {
+ syscall.CloseHandle(ino.handle)
+ return os.NewSyscallError("CreateIoCompletionPort", e)
+ }
+ watchEntry = &watch{
+ ino: ino,
+ path: dir,
+ names: make(map[string]uint64),
+ }
+ w.mu.Lock()
+ w.watches.set(ino, watchEntry)
+ w.mu.Unlock()
+ flags |= provisional
+ } else {
+ syscall.CloseHandle(ino.handle)
+ }
+ if pathname == dir {
+ watchEntry.mask |= flags
+ } else {
+ watchEntry.names[filepath.Base(pathname)] |= flags
+ }
+ if err = w.startRead(watchEntry); err != nil {
+ return err
+ }
+ if pathname == dir {
+ watchEntry.mask &= ^provisional
+ } else {
+ watchEntry.names[filepath.Base(pathname)] &= ^provisional
+ }
+ return nil
+}
+
+// Must run within the I/O thread.
+func (w *Watcher) remWatch(pathname string) error {
+ dir, err := getDir(pathname)
+ if err != nil {
+ return err
+ }
+ ino, err := getIno(dir)
+ if err != nil {
+ return err
+ }
+ w.mu.Lock()
+ watch := w.watches.get(ino)
+ w.mu.Unlock()
+ if watch == nil {
+ return fmt.Errorf("can't remove non-existent watch for: %s", pathname)
+ }
+ if pathname == dir {
+ w.sendEvent(watch.path, watch.mask&sys_FS_IGNORED)
+ watch.mask = 0
+ } else {
+ name := filepath.Base(pathname)
+ w.sendEvent(watch.path+"\\"+name, watch.names[name]&sys_FS_IGNORED)
+ delete(watch.names, name)
+ }
+ return w.startRead(watch)
+}
+
+// Must run within the I/O thread.
+func (w *Watcher) deleteWatch(watch *watch) {
+ for name, mask := range watch.names {
+ if mask&provisional == 0 {
+ w.sendEvent(watch.path+"\\"+name, mask&sys_FS_IGNORED)
+ }
+ delete(watch.names, name)
+ }
+ if watch.mask != 0 {
+ if watch.mask&provisional == 0 {
+ w.sendEvent(watch.path, watch.mask&sys_FS_IGNORED)
+ }
+ watch.mask = 0
+ }
+}
+
+// Must run within the I/O thread.
+func (w *Watcher) startRead(watch *watch) error {
+ if e := syscall.CancelIo(watch.ino.handle); e != nil {
+ w.Error <- os.NewSyscallError("CancelIo", e)
+ w.deleteWatch(watch)
+ }
+ mask := toWindowsFlags(watch.mask)
+ for _, m := range watch.names {
+ mask |= toWindowsFlags(m)
+ }
+ if mask == 0 {
+ if e := syscall.CloseHandle(watch.ino.handle); e != nil {
+ w.Error <- os.NewSyscallError("CloseHandle", e)
+ }
+ w.mu.Lock()
+ delete(w.watches[watch.ino.volume], watch.ino.index)
+ w.mu.Unlock()
+ return nil
+ }
+ e := syscall.ReadDirectoryChanges(watch.ino.handle, &watch.buf[0],
+ uint32(unsafe.Sizeof(watch.buf)), false, mask, nil, &watch.ov, 0)
+ if e != nil {
+ err := os.NewSyscallError("ReadDirectoryChanges", e)
+ if e == syscall.ERROR_ACCESS_DENIED && watch.mask&provisional == 0 {
+ // Watched directory was probably removed
+ if w.sendEvent(watch.path, watch.mask&sys_FS_DELETE_SELF) {
+ if watch.mask&sys_FS_ONESHOT != 0 {
+ watch.mask = 0
+ }
+ }
+ err = nil
+ }
+ w.deleteWatch(watch)
+ w.startRead(watch)
+ return err
+ }
+ return nil
+}
+
+// readEvents reads from the I/O completion port, converts the
+// received events into Event objects and sends them via the Event channel.
+// Entry point to the I/O thread.
+func (w *Watcher) readEvents() {
+ var (
+ n, key uint32
+ ov *syscall.Overlapped
+ )
+ runtime.LockOSThread()
+
+ for {
+ e := syscall.GetQueuedCompletionStatus(w.port, &n, &key, &ov, syscall.INFINITE)
+ watch := (*watch)(unsafe.Pointer(ov))
+
+ if watch == nil {
+ select {
+ case ch := <-w.quit:
+ w.mu.Lock()
+ var indexes []indexMap
+ for _, index := range w.watches {
+ indexes = append(indexes, index)
+ }
+ w.mu.Unlock()
+ for _, index := range indexes {
+ for _, watch := range index {
+ w.deleteWatch(watch)
+ w.startRead(watch)
+ }
+ }
+ var err error
+ if e := syscall.CloseHandle(w.port); e != nil {
+ err = os.NewSyscallError("CloseHandle", e)
+ }
+ close(w.internalEvent)
+ close(w.Error)
+ ch <- err
+ return
+ case in := <-w.input:
+ switch in.op {
+ case opAddWatch:
+ in.reply <- w.addWatch(in.path, uint64(in.flags))
+ case opRemoveWatch:
+ in.reply <- w.remWatch(in.path)
+ }
+ default:
+ }
+ continue
+ }
+
+ switch e {
+ case sys_ERROR_MORE_DATA:
+ if watch == nil {
+ w.Error <- errors.New("ERROR_MORE_DATA has unexpectedly null lpOverlapped buffer")
+ } else {
+ // The i/o succeeded but the buffer is full.
+ // In theory we should be building up a full packet.
+ // In practice we can get away with just carrying on.
+ n = uint32(unsafe.Sizeof(watch.buf))
+ }
+ case syscall.ERROR_ACCESS_DENIED:
+ // Watched directory was probably removed
+ w.sendEvent(watch.path, watch.mask&sys_FS_DELETE_SELF)
+ w.deleteWatch(watch)
+ w.startRead(watch)
+ continue
+ case syscall.ERROR_OPERATION_ABORTED:
+ // CancelIo was called on this handle
+ continue
+ default:
+ w.Error <- os.NewSyscallError("GetQueuedCompletionPort", e)
+ continue
+ case nil:
+ }
+
+ var offset uint32
+ for {
+ if n == 0 {
+ w.internalEvent <- &FileEvent{mask: sys_FS_Q_OVERFLOW}
+ w.Error <- errors.New("short read in readEvents()")
+ break
+ }
+
+ // Point "raw" to the event in the buffer
+ raw := (*syscall.FileNotifyInformation)(unsafe.Pointer(&watch.buf[offset]))
+ buf := (*[syscall.MAX_PATH]uint16)(unsafe.Pointer(&raw.FileName))
+ name := syscall.UTF16ToString(buf[:raw.FileNameLength/2])
+ fullname := watch.path + "\\" + name
+
+ var mask uint64
+ switch raw.Action {
+ case syscall.FILE_ACTION_REMOVED:
+ mask = sys_FS_DELETE_SELF
+ case syscall.FILE_ACTION_MODIFIED:
+ mask = sys_FS_MODIFY
+ case syscall.FILE_ACTION_RENAMED_OLD_NAME:
+ watch.rename = name
+ case syscall.FILE_ACTION_RENAMED_NEW_NAME:
+ if watch.names[watch.rename] != 0 {
+ watch.names[name] |= watch.names[watch.rename]
+ delete(watch.names, watch.rename)
+ mask = sys_FS_MOVE_SELF
+ }
+ }
+
+ sendNameEvent := func() {
+ if w.sendEvent(fullname, watch.names[name]&mask) {
+ if watch.names[name]&sys_FS_ONESHOT != 0 {
+ delete(watch.names, name)
+ }
+ }
+ }
+ if raw.Action != syscall.FILE_ACTION_RENAMED_NEW_NAME {
+ sendNameEvent()
+ }
+ if raw.Action == syscall.FILE_ACTION_REMOVED {
+ w.sendEvent(fullname, watch.names[name]&sys_FS_IGNORED)
+ delete(watch.names, name)
+ }
+ if w.sendEvent(fullname, watch.mask&toFSnotifyFlags(raw.Action)) {
+ if watch.mask&sys_FS_ONESHOT != 0 {
+ watch.mask = 0
+ }
+ }
+ if raw.Action == syscall.FILE_ACTION_RENAMED_NEW_NAME {
+ fullname = watch.path + "\\" + watch.rename
+ sendNameEvent()
+ }
+
+ // Move to the next event in the buffer
+ if raw.NextEntryOffset == 0 {
+ break
+ }
+ offset += raw.NextEntryOffset
+
+ // Error!
+ if offset >= n {
+ w.Error <- errors.New("Windows system assumed buffer larger than it is, events have likely been missed.")
+ break
+ }
+ }
+
+ if err := w.startRead(watch); err != nil {
+ w.Error <- err
+ }
+ }
+}
+
+func (w *Watcher) sendEvent(name string, mask uint64) bool {
+ if mask == 0 {
+ return false
+ }
+ event := &FileEvent{mask: uint32(mask), Name: name}
+ if mask&sys_FS_MOVE != 0 {
+ if mask&sys_FS_MOVED_FROM != 0 {
+ w.cookie++
+ }
+ event.cookie = w.cookie
+ }
+ select {
+ case ch := <-w.quit:
+ w.quit <- ch
+ case w.Event <- event:
+ }
+ return true
+}
+
+func toWindowsFlags(mask uint64) uint32 {
+ var m uint32
+ if mask&sys_FS_ACCESS != 0 {
+ m |= syscall.FILE_NOTIFY_CHANGE_LAST_ACCESS
+ }
+ if mask&sys_FS_MODIFY != 0 {
+ m |= syscall.FILE_NOTIFY_CHANGE_LAST_WRITE
+ }
+ if mask&sys_FS_ATTRIB != 0 {
+ m |= syscall.FILE_NOTIFY_CHANGE_ATTRIBUTES
+ }
+ if mask&(sys_FS_MOVE|sys_FS_CREATE|sys_FS_DELETE) != 0 {
+ m |= syscall.FILE_NOTIFY_CHANGE_FILE_NAME | syscall.FILE_NOTIFY_CHANGE_DIR_NAME
+ }
+ return m
+}
+
+func toFSnotifyFlags(action uint32) uint64 {
+ switch action {
+ case syscall.FILE_ACTION_ADDED:
+ return sys_FS_CREATE
+ case syscall.FILE_ACTION_REMOVED:
+ return sys_FS_DELETE
+ case syscall.FILE_ACTION_MODIFIED:
+ return sys_FS_MODIFY
+ case syscall.FILE_ACTION_RENAMED_OLD_NAME:
+ return sys_FS_MOVED_FROM
+ case syscall.FILE_ACTION_RENAMED_NEW_NAME:
+ return sys_FS_MOVED_TO
+ }
+ return 0
+}
diff --git a/vendor/github.com/prometheus/node_exporter/collector/collector.go b/vendor/github.com/prometheus/node_exporter/collector/collector.go
index 06c8924a0..e8840cc07 100644
--- a/vendor/github.com/prometheus/node_exporter/collector/collector.go
+++ b/vendor/github.com/prometheus/node_exporter/collector/collector.go
@@ -15,7 +15,6 @@
package collector
import (
- "fmt"
"sync"
"time"
@@ -83,10 +82,12 @@ func NewNodeCollector(filters ...string) (*nodeCollector, error) {
for _, filter := range filters {
enabled, exist := collectorState[filter]
if !exist {
- return nil, fmt.Errorf("missing collector: %s", filter)
+ log.Warnf("missing collector: %s", filter)
+ continue
}
if !*enabled {
- return nil, fmt.Errorf("disabled collector: %s", filter)
+ log.Warnf("disabled collector: %s", filter)
+ continue
}
f[filter] = true
}
diff --git a/vendor/gopkg.in.o/mgo.v2/bson/LICENSE b/vendor/gopkg.in.o/mgo.v2/bson/LICENSE
deleted file mode 100644
index 890326017..000000000
--- a/vendor/gopkg.in.o/mgo.v2/bson/LICENSE
+++ /dev/null
@@ -1,25 +0,0 @@
-BSON library for Go
-
-Copyright (c) 2010-2012 - Gustavo Niemeyer
-
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-1. Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/gopkg.in.o/mgo.v2/bson/bson.go b/vendor/gopkg.in.o/mgo.v2/bson/bson.go
deleted file mode 100644
index 7fb7f8cae..000000000
--- a/vendor/gopkg.in.o/mgo.v2/bson/bson.go
+++ /dev/null
@@ -1,738 +0,0 @@
-// BSON library for Go
-//
-// Copyright (c) 2010-2012 - Gustavo Niemeyer
-//
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Package bson is an implementation of the BSON specification for Go:
-//
-// http://bsonspec.org
-//
-// It was created as part of the mgo MongoDB driver for Go, but is standalone
-// and may be used on its own without the driver.
-package bson
-
-import (
- "bytes"
- "crypto/md5"
- "crypto/rand"
- "encoding/binary"
- "encoding/hex"
- "encoding/json"
- "errors"
- "fmt"
- "io"
- "os"
- "reflect"
- "runtime"
- "strings"
- "sync"
- "sync/atomic"
- "time"
-)
-
-// --------------------------------------------------------------------------
-// The public API.
-
-// A value implementing the bson.Getter interface will have its GetBSON
-// method called when the given value has to be marshalled, and the result
-// of this method will be marshaled in place of the actual object.
-//
-// If GetBSON returns return a non-nil error, the marshalling procedure
-// will stop and error out with the provided value.
-type Getter interface {
- GetBSON() (interface{}, error)
-}
-
-// A value implementing the bson.Setter interface will receive the BSON
-// value via the SetBSON method during unmarshaling, and the object
-// itself will not be changed as usual.
-//
-// If setting the value works, the method should return nil or alternatively
-// bson.SetZero to set the respective field to its zero value (nil for
-// pointer types). If SetBSON returns a value of type bson.TypeError, the
-// BSON value will be omitted from a map or slice being decoded and the
-// unmarshalling will continue. If it returns any other non-nil error, the
-// unmarshalling procedure will stop and error out with the provided value.
-//
-// This interface is generally useful in pointer receivers, since the method
-// will want to change the receiver. A type field that implements the Setter
-// interface doesn't have to be a pointer, though.
-//
-// Unlike the usual behavior, unmarshalling onto a value that implements a
-// Setter interface will NOT reset the value to its zero state. This allows
-// the value to decide by itself how to be unmarshalled.
-//
-// For example:
-//
-// type MyString string
-//
-// func (s *MyString) SetBSON(raw bson.Raw) error {
-// return raw.Unmarshal(s)
-// }
-//
-type Setter interface {
- SetBSON(raw Raw) error
-}
-
-// SetZero may be returned from a SetBSON method to have the value set to
-// its respective zero value. When used in pointer values, this will set the
-// field to nil rather than to the pre-allocated value.
-var SetZero = errors.New("set to zero")
-
-// M is a convenient alias for a map[string]interface{} map, useful for
-// dealing with BSON in a native way. For instance:
-//
-// bson.M{"a": 1, "b": true}
-//
-// There's no special handling for this type in addition to what's done anyway
-// for an equivalent map type. Elements in the map will be dumped in an
-// undefined ordered. See also the bson.D type for an ordered alternative.
-type M map[string]interface{}
-
-// D represents a BSON document containing ordered elements. For example:
-//
-// bson.D{{"a", 1}, {"b", true}}
-//
-// In some situations, such as when creating indexes for MongoDB, the order in
-// which the elements are defined is important. If the order is not important,
-// using a map is generally more comfortable. See bson.M and bson.RawD.
-type D []DocElem
-
-// DocElem is an element of the bson.D document representation.
-type DocElem struct {
- Name string
- Value interface{}
-}
-
-// Map returns a map out of the ordered element name/value pairs in d.
-func (d D) Map() (m M) {
- m = make(M, len(d))
- for _, item := range d {
- m[item.Name] = item.Value
- }
- return m
-}
-
-// The Raw type represents raw unprocessed BSON documents and elements.
-// Kind is the kind of element as defined per the BSON specification, and
-// Data is the raw unprocessed data for the respective element.
-// Using this type it is possible to unmarshal or marshal values partially.
-//
-// Relevant documentation:
-//
-// http://bsonspec.org/#/specification
-//
-type Raw struct {
- Kind byte
- Data []byte
-}
-
-// RawD represents a BSON document containing raw unprocessed elements.
-// This low-level representation may be useful when lazily processing
-// documents of uncertain content, or when manipulating the raw content
-// documents in general.
-type RawD []RawDocElem
-
-// See the RawD type.
-type RawDocElem struct {
- Name string
- Value Raw
-}
-
-// ObjectId is a unique ID identifying a BSON value. It must be exactly 12 bytes
-// long. MongoDB objects by default have such a property set in their "_id"
-// property.
-//
-// http://www.mongodb.org/display/DOCS/Object+IDs
-type ObjectId string
-
-// ObjectIdHex returns an ObjectId from the provided hex representation.
-// Calling this function with an invalid hex representation will
-// cause a runtime panic. See the IsObjectIdHex function.
-func ObjectIdHex(s string) ObjectId {
- d, err := hex.DecodeString(s)
- if err != nil || len(d) != 12 {
- panic(fmt.Sprintf("invalid input to ObjectIdHex: %q", s))
- }
- return ObjectId(d)
-}
-
-// IsObjectIdHex returns whether s is a valid hex representation of
-// an ObjectId. See the ObjectIdHex function.
-func IsObjectIdHex(s string) bool {
- if len(s) != 24 {
- return false
- }
- _, err := hex.DecodeString(s)
- return err == nil
-}
-
-// objectIdCounter is atomically incremented when generating a new ObjectId
-// using NewObjectId() function. It's used as a counter part of an id.
-var objectIdCounter uint32 = readRandomUint32()
-
-// readRandomUint32 returns a random objectIdCounter.
-func readRandomUint32() uint32 {
- var b [4]byte
- _, err := io.ReadFull(rand.Reader, b[:])
- if err != nil {
- panic(fmt.Errorf("cannot read random object id: %v", err))
- }
- return uint32((uint32(b[0]) << 0) | (uint32(b[1]) << 8) | (uint32(b[2]) << 16) | (uint32(b[3]) << 24))
-}
-
-// machineId stores machine id generated once and used in subsequent calls
-// to NewObjectId function.
-var machineId = readMachineId()
-var processId = os.Getpid()
-
-// readMachineId generates and returns a machine id.
-// If this function fails to get the hostname it will cause a runtime error.
-func readMachineId() []byte {
- var sum [3]byte
- id := sum[:]
- hostname, err1 := os.Hostname()
- if err1 != nil {
- _, err2 := io.ReadFull(rand.Reader, id)
- if err2 != nil {
- panic(fmt.Errorf("cannot get hostname: %v; %v", err1, err2))
- }
- return id
- }
- hw := md5.New()
- hw.Write([]byte(hostname))
- copy(id, hw.Sum(nil))
- return id
-}
-
-// NewObjectId returns a new unique ObjectId.
-func NewObjectId() ObjectId {
- var b [12]byte
- // Timestamp, 4 bytes, big endian
- binary.BigEndian.PutUint32(b[:], uint32(time.Now().Unix()))
- // Machine, first 3 bytes of md5(hostname)
- b[4] = machineId[0]
- b[5] = machineId[1]
- b[6] = machineId[2]
- // Pid, 2 bytes, specs don't specify endianness, but we use big endian.
- b[7] = byte(processId >> 8)
- b[8] = byte(processId)
- // Increment, 3 bytes, big endian
- i := atomic.AddUint32(&objectIdCounter, 1)
- b[9] = byte(i >> 16)
- b[10] = byte(i >> 8)
- b[11] = byte(i)
- return ObjectId(b[:])
-}
-
-// NewObjectIdWithTime returns a dummy ObjectId with the timestamp part filled
-// with the provided number of seconds from epoch UTC, and all other parts
-// filled with zeroes. It's not safe to insert a document with an id generated
-// by this method, it is useful only for queries to find documents with ids
-// generated before or after the specified timestamp.
-func NewObjectIdWithTime(t time.Time) ObjectId {
- var b [12]byte
- binary.BigEndian.PutUint32(b[:4], uint32(t.Unix()))
- return ObjectId(string(b[:]))
-}
-
-// String returns a hex string representation of the id.
-// Example: ObjectIdHex("4d88e15b60f486e428412dc9").
-func (id ObjectId) String() string {
- return fmt.Sprintf(`ObjectIdHex("%x")`, string(id))
-}
-
-// Hex returns a hex representation of the ObjectId.
-func (id ObjectId) Hex() string {
- return hex.EncodeToString([]byte(id))
-}
-
-// MarshalJSON turns a bson.ObjectId into a json.Marshaller.
-func (id ObjectId) MarshalJSON() ([]byte, error) {
- return []byte(fmt.Sprintf(`"%x"`, string(id))), nil
-}
-
-var nullBytes = []byte("null")
-
-// UnmarshalJSON turns *bson.ObjectId into a json.Unmarshaller.
-func (id *ObjectId) UnmarshalJSON(data []byte) error {
- if len(data) > 0 && (data[0] == '{' || data[0] == 'O') {
- var v struct {
- Id json.RawMessage `json:"$oid"`
- Func struct {
- Id json.RawMessage
- } `json:"$oidFunc"`
- }
- err := jdec(data, &v)
- if err == nil {
- if len(v.Id) > 0 {
- data = []byte(v.Id)
- } else {
- data = []byte(v.Func.Id)
- }
- }
- }
- if len(data) == 2 && data[0] == '"' && data[1] == '"' || bytes.Equal(data, nullBytes) {
- *id = ""
- return nil
- }
- if len(data) != 26 || data[0] != '"' || data[25] != '"' {
- return errors.New(fmt.Sprintf("invalid ObjectId in JSON: %s", string(data)))
- }
- var buf [12]byte
- _, err := hex.Decode(buf[:], data[1:25])
- if err != nil {
- return errors.New(fmt.Sprintf("invalid ObjectId in JSON: %s (%s)", string(data), err))
- }
- *id = ObjectId(string(buf[:]))
- return nil
-}
-
-// MarshalText turns bson.ObjectId into an encoding.TextMarshaler.
-func (id ObjectId) MarshalText() ([]byte, error) {
- return []byte(fmt.Sprintf("%x", string(id))), nil
-}
-
-// UnmarshalText turns *bson.ObjectId into an encoding.TextUnmarshaler.
-func (id *ObjectId) UnmarshalText(data []byte) error {
- if len(data) == 1 && data[0] == ' ' || len(data) == 0 {
- *id = ""
- return nil
- }
- if len(data) != 24 {
- return fmt.Errorf("invalid ObjectId: %s", data)
- }
- var buf [12]byte
- _, err := hex.Decode(buf[:], data[:])
- if err != nil {
- return fmt.Errorf("invalid ObjectId: %s (%s)", data, err)
- }
- *id = ObjectId(string(buf[:]))
- return nil
-}
-
-// Valid returns true if id is valid. A valid id must contain exactly 12 bytes.
-func (id ObjectId) Valid() bool {
- return len(id) == 12
-}
-
-// byteSlice returns byte slice of id from start to end.
-// Calling this function with an invalid id will cause a runtime panic.
-func (id ObjectId) byteSlice(start, end int) []byte {
- if len(id) != 12 {
- panic(fmt.Sprintf("invalid ObjectId: %q", string(id)))
- }
- return []byte(string(id)[start:end])
-}
-
-// Time returns the timestamp part of the id.
-// It's a runtime error to call this method with an invalid id.
-func (id ObjectId) Time() time.Time {
- // First 4 bytes of ObjectId is 32-bit big-endian seconds from epoch.
- secs := int64(binary.BigEndian.Uint32(id.byteSlice(0, 4)))
- return time.Unix(secs, 0)
-}
-
-// Machine returns the 3-byte machine id part of the id.
-// It's a runtime error to call this method with an invalid id.
-func (id ObjectId) Machine() []byte {
- return id.byteSlice(4, 7)
-}
-
-// Pid returns the process id part of the id.
-// It's a runtime error to call this method with an invalid id.
-func (id ObjectId) Pid() uint16 {
- return binary.BigEndian.Uint16(id.byteSlice(7, 9))
-}
-
-// Counter returns the incrementing value part of the id.
-// It's a runtime error to call this method with an invalid id.
-func (id ObjectId) Counter() int32 {
- b := id.byteSlice(9, 12)
- // Counter is stored as big-endian 3-byte value
- return int32(uint32(b[0])<<16 | uint32(b[1])<<8 | uint32(b[2]))
-}
-
-// The Symbol type is similar to a string and is used in languages with a
-// distinct symbol type.
-type Symbol string
-
-// Now returns the current time with millisecond precision. MongoDB stores
-// timestamps with the same precision, so a Time returned from this method
-// will not change after a roundtrip to the database. That's the only reason
-// why this function exists. Using the time.Now function also works fine
-// otherwise.
-func Now() time.Time {
- return time.Unix(0, time.Now().UnixNano()/1e6*1e6)
-}
-
-// MongoTimestamp is a special internal type used by MongoDB that for some
-// strange reason has its own datatype defined in BSON.
-type MongoTimestamp int64
-
-type orderKey int64
-
-// MaxKey is a special value that compares higher than all other possible BSON
-// values in a MongoDB database.
-var MaxKey = orderKey(1<<63 - 1)
-
-// MinKey is a special value that compares lower than all other possible BSON
-// values in a MongoDB database.
-var MinKey = orderKey(-1 << 63)
-
-type undefined struct{}
-
-// Undefined represents the undefined BSON value.
-var Undefined undefined
-
-// Binary is a representation for non-standard binary values. Any kind should
-// work, but the following are known as of this writing:
-//
-// 0x00 - Generic. This is decoded as []byte(data), not Binary{0x00, data}.
-// 0x01 - Function (!?)
-// 0x02 - Obsolete generic.
-// 0x03 - UUID
-// 0x05 - MD5
-// 0x80 - User defined.
-//
-type Binary struct {
- Kind byte
- Data []byte
-}
-
-// RegEx represents a regular expression. The Options field may contain
-// individual characters defining the way in which the pattern should be
-// applied, and must be sorted. Valid options as of this writing are 'i' for
-// case insensitive matching, 'm' for multi-line matching, 'x' for verbose
-// mode, 'l' to make \w, \W, and similar be locale-dependent, 's' for dot-all
-// mode (a '.' matches everything), and 'u' to make \w, \W, and similar match
-// unicode. The value of the Options parameter is not verified before being
-// marshaled into the BSON format.
-type RegEx struct {
- Pattern string
- Options string
-}
-
-// JavaScript is a type that holds JavaScript code. If Scope is non-nil, it
-// will be marshaled as a mapping from identifiers to values that may be
-// used when evaluating the provided Code.
-type JavaScript struct {
- Code string
- Scope interface{}
-}
-
-// DBPointer refers to a document id in a namespace.
-//
-// This type is deprecated in the BSON specification and should not be used
-// except for backwards compatibility with ancient applications.
-type DBPointer struct {
- Namespace string
- Id ObjectId
-}
-
-const initialBufferSize = 64
-
-func handleErr(err *error) {
- if r := recover(); r != nil {
- if _, ok := r.(runtime.Error); ok {
- panic(r)
- } else if _, ok := r.(externalPanic); ok {
- panic(r)
- } else if s, ok := r.(string); ok {
- *err = errors.New(s)
- } else if e, ok := r.(error); ok {
- *err = e
- } else {
- panic(r)
- }
- }
-}
-
-// Marshal serializes the in value, which may be a map or a struct value.
-// In the case of struct values, only exported fields will be serialized,
-// and the order of serialized fields will match that of the struct itself.
-// The lowercased field name is used as the key for each exported field,
-// but this behavior may be changed using the respective field tag.
-// The tag may also contain flags to tweak the marshalling behavior for
-// the field. The tag formats accepted are:
-//
-// "[][,[,]]"
-//
-// `(...) bson:"[][,[,]]" (...)`
-//
-// The following flags are currently supported:
-//
-// omitempty Only include the field if it's not set to the zero
-// value for the type or to empty slices or maps.
-//
-// minsize Marshal an int64 value as an int32, if that's feasible
-// while preserving the numeric value.
-//
-// inline Inline the field, which must be a struct or a map,
-// causing all of its fields or keys to be processed as if
-// they were part of the outer struct. For maps, keys must
-// not conflict with the bson keys of other struct fields.
-//
-// Some examples:
-//
-// type T struct {
-// A bool
-// B int "myb"
-// C string "myc,omitempty"
-// D string `bson:",omitempty" json:"jsonkey"`
-// E int64 ",minsize"
-// F int64 "myf,omitempty,minsize"
-// }
-//
-func Marshal(in interface{}) (out []byte, err error) {
- defer handleErr(&err)
- e := &encoder{make([]byte, 0, initialBufferSize)}
- e.addDoc(reflect.ValueOf(in))
- return e.out, nil
-}
-
-// Unmarshal deserializes data from in into the out value. The out value
-// must be a map, a pointer to a struct, or a pointer to a bson.D value.
-// In the case of struct values, only exported fields will be deserialized.
-// The lowercased field name is used as the key for each exported field,
-// but this behavior may be changed using the respective field tag.
-// The tag may also contain flags to tweak the marshalling behavior for
-// the field. The tag formats accepted are:
-//
-// "[][,[,]]"
-//
-// `(...) bson:"[][,[,]]" (...)`
-//
-// The following flags are currently supported during unmarshal (see the
-// Marshal method for other flags):
-//
-// inline Inline the field, which must be a struct or a map.
-// Inlined structs are handled as if its fields were part
-// of the outer struct. An inlined map causes keys that do
-// not match any other struct field to be inserted in the
-// map rather than being discarded as usual.
-//
-// The target field or element types of out may not necessarily match
-// the BSON values of the provided data. The following conversions are
-// made automatically:
-//
-// - Numeric types are converted if at least the integer part of the
-// value would be preserved correctly
-// - Bools are converted to numeric types as 1 or 0
-// - Numeric types are converted to bools as true if not 0 or false otherwise
-// - Binary and string BSON data is converted to a string, array or byte slice
-//
-// If the value would not fit the type and cannot be converted, it's
-// silently skipped.
-//
-// Pointer values are initialized when necessary.
-func Unmarshal(in []byte, out interface{}) (err error) {
- if raw, ok := out.(*Raw); ok {
- raw.Kind = 3
- raw.Data = in
- return nil
- }
- defer handleErr(&err)
- v := reflect.ValueOf(out)
- switch v.Kind() {
- case reflect.Ptr:
- fallthrough
- case reflect.Map:
- d := newDecoder(in)
- d.readDocTo(v)
- case reflect.Struct:
- return errors.New("Unmarshal can't deal with struct values. Use a pointer.")
- default:
- return errors.New("Unmarshal needs a map or a pointer to a struct.")
- }
- return nil
-}
-
-// Unmarshal deserializes raw into the out value. If the out value type
-// is not compatible with raw, a *bson.TypeError is returned.
-//
-// See the Unmarshal function documentation for more details on the
-// unmarshalling process.
-func (raw Raw) Unmarshal(out interface{}) (err error) {
- defer handleErr(&err)
- v := reflect.ValueOf(out)
- switch v.Kind() {
- case reflect.Ptr:
- v = v.Elem()
- fallthrough
- case reflect.Map:
- d := newDecoder(raw.Data)
- good := d.readElemTo(v, raw.Kind)
- if !good {
- return &TypeError{v.Type(), raw.Kind}
- }
- case reflect.Struct:
- return errors.New("Raw Unmarshal can't deal with struct values. Use a pointer.")
- default:
- return errors.New("Raw Unmarshal needs a map or a valid pointer.")
- }
- return nil
-}
-
-type TypeError struct {
- Type reflect.Type
- Kind byte
-}
-
-func (e *TypeError) Error() string {
- return fmt.Sprintf("BSON kind 0x%02x isn't compatible with type %s", e.Kind, e.Type.String())
-}
-
-// --------------------------------------------------------------------------
-// Maintain a mapping of keys to structure field indexes
-
-type structInfo struct {
- FieldsMap map[string]fieldInfo
- FieldsList []fieldInfo
- InlineMap int
- Zero reflect.Value
-}
-
-type fieldInfo struct {
- Key string
- Num int
- OmitEmpty bool
- MinSize bool
- Inline []int
-}
-
-var structMap = make(map[reflect.Type]*structInfo)
-var structMapMutex sync.RWMutex
-
-type externalPanic string
-
-func (e externalPanic) String() string {
- return string(e)
-}
-
-func getStructInfo(st reflect.Type) (*structInfo, error) {
- structMapMutex.RLock()
- sinfo, found := structMap[st]
- structMapMutex.RUnlock()
- if found {
- return sinfo, nil
- }
- n := st.NumField()
- fieldsMap := make(map[string]fieldInfo)
- fieldsList := make([]fieldInfo, 0, n)
- inlineMap := -1
- for i := 0; i != n; i++ {
- field := st.Field(i)
- if field.PkgPath != "" && !field.Anonymous {
- continue // Private field
- }
-
- info := fieldInfo{Num: i}
-
- tag := field.Tag.Get("bson")
- if tag == "" && strings.Index(string(field.Tag), ":") < 0 {
- tag = string(field.Tag)
- }
- if tag == "-" {
- continue
- }
-
- inline := false
- fields := strings.Split(tag, ",")
- if len(fields) > 1 {
- for _, flag := range fields[1:] {
- switch flag {
- case "omitempty":
- info.OmitEmpty = true
- case "minsize":
- info.MinSize = true
- case "inline":
- inline = true
- default:
- msg := fmt.Sprintf("Unsupported flag %q in tag %q of type %s", flag, tag, st)
- panic(externalPanic(msg))
- }
- }
- tag = fields[0]
- }
-
- if inline {
- switch field.Type.Kind() {
- case reflect.Map:
- if inlineMap >= 0 {
- return nil, errors.New("Multiple ,inline maps in struct " + st.String())
- }
- if field.Type.Key() != reflect.TypeOf("") {
- return nil, errors.New("Option ,inline needs a map with string keys in struct " + st.String())
- }
- inlineMap = info.Num
- case reflect.Struct:
- sinfo, err := getStructInfo(field.Type)
- if err != nil {
- return nil, err
- }
- for _, finfo := range sinfo.FieldsList {
- if _, found := fieldsMap[finfo.Key]; found {
- msg := "Duplicated key '" + finfo.Key + "' in struct " + st.String()
- return nil, errors.New(msg)
- }
- if finfo.Inline == nil {
- finfo.Inline = []int{i, finfo.Num}
- } else {
- finfo.Inline = append([]int{i}, finfo.Inline...)
- }
- fieldsMap[finfo.Key] = finfo
- fieldsList = append(fieldsList, finfo)
- }
- default:
- panic("Option ,inline needs a struct value or map field")
- }
- continue
- }
-
- if tag != "" {
- info.Key = tag
- } else {
- info.Key = strings.ToLower(field.Name)
- }
-
- if _, found = fieldsMap[info.Key]; found {
- msg := "Duplicated key '" + info.Key + "' in struct " + st.String()
- return nil, errors.New(msg)
- }
-
- fieldsList = append(fieldsList, info)
- fieldsMap[info.Key] = info
- }
- sinfo = &structInfo{
- fieldsMap,
- fieldsList,
- inlineMap,
- reflect.New(st).Elem(),
- }
- structMapMutex.Lock()
- structMap[st] = sinfo
- structMapMutex.Unlock()
- return sinfo, nil
-}
diff --git a/vendor/gopkg.in.o/mgo.v2/bson/bson_test.go b/vendor/gopkg.in.o/mgo.v2/bson/bson_test.go
deleted file mode 100644
index 37451f9fd..000000000
--- a/vendor/gopkg.in.o/mgo.v2/bson/bson_test.go
+++ /dev/null
@@ -1,1832 +0,0 @@
-// BSON library for Go
-//
-// Copyright (c) 2010-2012 - Gustavo Niemeyer
-//
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// gobson - BSON library for Go.
-
-package bson_test
-
-import (
- "encoding/binary"
- "encoding/hex"
- "encoding/json"
- "encoding/xml"
- "errors"
- "net/url"
- "reflect"
- "strings"
- "testing"
- "time"
-
- . "gopkg.in/check.v1"
- "gopkg.in/mgo.v2/bson"
- "gopkg.in/yaml.v2"
-)
-
-func TestAll(t *testing.T) {
- TestingT(t)
-}
-
-type S struct{}
-
-var _ = Suite(&S{})
-
-// Wrap up the document elements contained in data, prepending the int32
-// length of the data, and appending the '\x00' value closing the document.
-func wrapInDoc(data string) string {
- result := make([]byte, len(data)+5)
- binary.LittleEndian.PutUint32(result, uint32(len(result)))
- copy(result[4:], []byte(data))
- return string(result)
-}
-
-func makeZeroDoc(value interface{}) (zero interface{}) {
- v := reflect.ValueOf(value)
- t := v.Type()
- switch t.Kind() {
- case reflect.Map:
- mv := reflect.MakeMap(t)
- zero = mv.Interface()
- case reflect.Ptr:
- pv := reflect.New(v.Type().Elem())
- zero = pv.Interface()
- case reflect.Slice, reflect.Int, reflect.Int64, reflect.Struct:
- zero = reflect.New(t).Interface()
- default:
- panic("unsupported doc type: " + t.Name())
- }
- return zero
-}
-
-func testUnmarshal(c *C, data string, obj interface{}) {
- zero := makeZeroDoc(obj)
- err := bson.Unmarshal([]byte(data), zero)
- c.Assert(err, IsNil)
- c.Assert(zero, DeepEquals, obj)
-}
-
-type testItemType struct {
- obj interface{}
- data string
-}
-
-// --------------------------------------------------------------------------
-// Samples from bsonspec.org:
-
-var sampleItems = []testItemType{
- {bson.M{"hello": "world"},
- "\x16\x00\x00\x00\x02hello\x00\x06\x00\x00\x00world\x00\x00"},
- {bson.M{"BSON": []interface{}{"awesome", float64(5.05), 1986}},
- "1\x00\x00\x00\x04BSON\x00&\x00\x00\x00\x020\x00\x08\x00\x00\x00" +
- "awesome\x00\x011\x00333333\x14@\x102\x00\xc2\x07\x00\x00\x00\x00"},
-}
-
-func (s *S) TestMarshalSampleItems(c *C) {
- for i, item := range sampleItems {
- data, err := bson.Marshal(item.obj)
- c.Assert(err, IsNil)
- c.Assert(string(data), Equals, item.data, Commentf("Failed on item %d", i))
- }
-}
-
-func (s *S) TestUnmarshalSampleItems(c *C) {
- for i, item := range sampleItems {
- value := bson.M{}
- err := bson.Unmarshal([]byte(item.data), value)
- c.Assert(err, IsNil)
- c.Assert(value, DeepEquals, item.obj, Commentf("Failed on item %d", i))
- }
-}
-
-// --------------------------------------------------------------------------
-// Every type, ordered by the type flag. These are not wrapped with the
-// length and last \x00 from the document. wrapInDoc() computes them.
-// Note that all of them should be supported as two-way conversions.
-
-var allItems = []testItemType{
- {bson.M{},
- ""},
- {bson.M{"_": float64(5.05)},
- "\x01_\x00333333\x14@"},
- {bson.M{"_": "yo"},
- "\x02_\x00\x03\x00\x00\x00yo\x00"},
- {bson.M{"_": bson.M{"a": true}},
- "\x03_\x00\x09\x00\x00\x00\x08a\x00\x01\x00"},
- {bson.M{"_": []interface{}{true, false}},
- "\x04_\x00\r\x00\x00\x00\x080\x00\x01\x081\x00\x00\x00"},
- {bson.M{"_": []byte("yo")},
- "\x05_\x00\x02\x00\x00\x00\x00yo"},
- {bson.M{"_": bson.Binary{0x80, []byte("udef")}},
- "\x05_\x00\x04\x00\x00\x00\x80udef"},
- {bson.M{"_": bson.Undefined}, // Obsolete, but still seen in the wild.
- "\x06_\x00"},
- {bson.M{"_": bson.ObjectId("0123456789ab")},
- "\x07_\x000123456789ab"},
- {bson.M{"_": bson.DBPointer{"testnamespace", bson.ObjectId("0123456789ab")}},
- "\x0C_\x00\x0e\x00\x00\x00testnamespace\x000123456789ab"},
- {bson.M{"_": false},
- "\x08_\x00\x00"},
- {bson.M{"_": true},
- "\x08_\x00\x01"},
- {bson.M{"_": time.Unix(0, 258e6)}, // Note the NS <=> MS conversion.
- "\x09_\x00\x02\x01\x00\x00\x00\x00\x00\x00"},
- {bson.M{"_": nil},
- "\x0A_\x00"},
- {bson.M{"_": bson.RegEx{"ab", "cd"}},
- "\x0B_\x00ab\x00cd\x00"},
- {bson.M{"_": bson.JavaScript{"code", nil}},
- "\x0D_\x00\x05\x00\x00\x00code\x00"},
- {bson.M{"_": bson.Symbol("sym")},
- "\x0E_\x00\x04\x00\x00\x00sym\x00"},
- {bson.M{"_": bson.JavaScript{"code", bson.M{"": nil}}},
- "\x0F_\x00\x14\x00\x00\x00\x05\x00\x00\x00code\x00" +
- "\x07\x00\x00\x00\x0A\x00\x00"},
- {bson.M{"_": 258},
- "\x10_\x00\x02\x01\x00\x00"},
- {bson.M{"_": bson.MongoTimestamp(258)},
- "\x11_\x00\x02\x01\x00\x00\x00\x00\x00\x00"},
- {bson.M{"_": int64(258)},
- "\x12_\x00\x02\x01\x00\x00\x00\x00\x00\x00"},
- {bson.M{"_": int64(258 << 32)},
- "\x12_\x00\x00\x00\x00\x00\x02\x01\x00\x00"},
- {bson.M{"_": bson.MaxKey},
- "\x7F_\x00"},
- {bson.M{"_": bson.MinKey},
- "\xFF_\x00"},
-}
-
-func (s *S) TestMarshalAllItems(c *C) {
- for i, item := range allItems {
- data, err := bson.Marshal(item.obj)
- c.Assert(err, IsNil)
- c.Assert(string(data), Equals, wrapInDoc(item.data), Commentf("Failed on item %d: %#v", i, item))
- }
-}
-
-func (s *S) TestUnmarshalAllItems(c *C) {
- for i, item := range allItems {
- value := bson.M{}
- err := bson.Unmarshal([]byte(wrapInDoc(item.data)), value)
- c.Assert(err, IsNil)
- c.Assert(value, DeepEquals, item.obj, Commentf("Failed on item %d: %#v", i, item))
- }
-}
-
-func (s *S) TestUnmarshalRawAllItems(c *C) {
- for i, item := range allItems {
- if len(item.data) == 0 {
- continue
- }
- value := item.obj.(bson.M)["_"]
- if value == nil {
- continue
- }
- pv := reflect.New(reflect.ValueOf(value).Type())
- raw := bson.Raw{item.data[0], []byte(item.data[3:])}
- c.Logf("Unmarshal raw: %#v, %#v", raw, pv.Interface())
- err := raw.Unmarshal(pv.Interface())
- c.Assert(err, IsNil)
- c.Assert(pv.Elem().Interface(), DeepEquals, value, Commentf("Failed on item %d: %#v", i, item))
- }
-}
-
-func (s *S) TestUnmarshalRawIncompatible(c *C) {
- raw := bson.Raw{0x08, []byte{0x01}} // true
- err := raw.Unmarshal(&struct{}{})
- c.Assert(err, ErrorMatches, "BSON kind 0x08 isn't compatible with type struct \\{\\}")
-}
-
-func (s *S) TestUnmarshalZeroesStruct(c *C) {
- data, err := bson.Marshal(bson.M{"b": 2})
- c.Assert(err, IsNil)
- type T struct{ A, B int }
- v := T{A: 1}
- err = bson.Unmarshal(data, &v)
- c.Assert(err, IsNil)
- c.Assert(v.A, Equals, 0)
- c.Assert(v.B, Equals, 2)
-}
-
-func (s *S) TestUnmarshalZeroesMap(c *C) {
- data, err := bson.Marshal(bson.M{"b": 2})
- c.Assert(err, IsNil)
- m := bson.M{"a": 1}
- err = bson.Unmarshal(data, &m)
- c.Assert(err, IsNil)
- c.Assert(m, DeepEquals, bson.M{"b": 2})
-}
-
-func (s *S) TestUnmarshalNonNilInterface(c *C) {
- data, err := bson.Marshal(bson.M{"b": 2})
- c.Assert(err, IsNil)
- m := bson.M{"a": 1}
- var i interface{}
- i = m
- err = bson.Unmarshal(data, &i)
- c.Assert(err, IsNil)
- c.Assert(i, DeepEquals, bson.M{"b": 2})
- c.Assert(m, DeepEquals, bson.M{"a": 1})
-}
-
-// --------------------------------------------------------------------------
-// Some one way marshaling operations which would unmarshal differently.
-
-var oneWayMarshalItems = []testItemType{
- // These are being passed as pointers, and will unmarshal as values.
- {bson.M{"": &bson.Binary{0x02, []byte("old")}},
- "\x05\x00\x07\x00\x00\x00\x02\x03\x00\x00\x00old"},
- {bson.M{"": &bson.Binary{0x80, []byte("udef")}},
- "\x05\x00\x04\x00\x00\x00\x80udef"},
- {bson.M{"": &bson.RegEx{"ab", "cd"}},
- "\x0B\x00ab\x00cd\x00"},
- {bson.M{"": &bson.JavaScript{"code", nil}},
- "\x0D\x00\x05\x00\x00\x00code\x00"},
- {bson.M{"": &bson.JavaScript{"code", bson.M{"": nil}}},
- "\x0F\x00\x14\x00\x00\x00\x05\x00\x00\x00code\x00" +
- "\x07\x00\x00\x00\x0A\x00\x00"},
-
- // There's no float32 type in BSON. Will encode as a float64.
- {bson.M{"": float32(5.05)},
- "\x01\x00\x00\x00\x00@33\x14@"},
-
- // The array will be unmarshaled as a slice instead.
- {bson.M{"": [2]bool{true, false}},
- "\x04\x00\r\x00\x00\x00\x080\x00\x01\x081\x00\x00\x00"},
-
- // The typed slice will be unmarshaled as []interface{}.
- {bson.M{"": []bool{true, false}},
- "\x04\x00\r\x00\x00\x00\x080\x00\x01\x081\x00\x00\x00"},
-
- // Will unmarshal as a []byte.
- {bson.M{"": bson.Binary{0x00, []byte("yo")}},
- "\x05\x00\x02\x00\x00\x00\x00yo"},
- {bson.M{"": bson.Binary{0x02, []byte("old")}},
- "\x05\x00\x07\x00\x00\x00\x02\x03\x00\x00\x00old"},
-
- // No way to preserve the type information here. We might encode as a zero
- // value, but this would mean that pointer values in structs wouldn't be
- // able to correctly distinguish between unset and set to the zero value.
- {bson.M{"": (*byte)(nil)},
- "\x0A\x00"},
-
- // No int types smaller than int32 in BSON. Could encode this as a char,
- // but it would still be ambiguous, take more, and be awkward in Go when
- // loaded without typing information.
- {bson.M{"": byte(8)},
- "\x10\x00\x08\x00\x00\x00"},
-
- // There are no unsigned types in BSON. Will unmarshal as int32 or int64.
- {bson.M{"": uint32(258)},
- "\x10\x00\x02\x01\x00\x00"},
- {bson.M{"": uint64(258)},
- "\x12\x00\x02\x01\x00\x00\x00\x00\x00\x00"},
- {bson.M{"": uint64(258 << 32)},
- "\x12\x00\x00\x00\x00\x00\x02\x01\x00\x00"},
-
- // This will unmarshal as int.
- {bson.M{"": int32(258)},
- "\x10\x00\x02\x01\x00\x00"},
-
- // That's a special case. The unsigned value is too large for an int32,
- // so an int64 is used instead.
- {bson.M{"": uint32(1<<32 - 1)},
- "\x12\x00\xFF\xFF\xFF\xFF\x00\x00\x00\x00"},
- {bson.M{"": uint(1<<32 - 1)},
- "\x12\x00\xFF\xFF\xFF\xFF\x00\x00\x00\x00"},
-}
-
-func (s *S) TestOneWayMarshalItems(c *C) {
- for i, item := range oneWayMarshalItems {
- data, err := bson.Marshal(item.obj)
- c.Assert(err, IsNil)
- c.Assert(string(data), Equals, wrapInDoc(item.data),
- Commentf("Failed on item %d", i))
- }
-}
-
-// --------------------------------------------------------------------------
-// Two-way tests for user-defined structures using the samples
-// from bsonspec.org.
-
-type specSample1 struct {
- Hello string
-}
-
-type specSample2 struct {
- BSON []interface{} "BSON"
-}
-
-var structSampleItems = []testItemType{
- {&specSample1{"world"},
- "\x16\x00\x00\x00\x02hello\x00\x06\x00\x00\x00world\x00\x00"},
- {&specSample2{[]interface{}{"awesome", float64(5.05), 1986}},
- "1\x00\x00\x00\x04BSON\x00&\x00\x00\x00\x020\x00\x08\x00\x00\x00" +
- "awesome\x00\x011\x00333333\x14@\x102\x00\xc2\x07\x00\x00\x00\x00"},
-}
-
-func (s *S) TestMarshalStructSampleItems(c *C) {
- for i, item := range structSampleItems {
- data, err := bson.Marshal(item.obj)
- c.Assert(err, IsNil)
- c.Assert(string(data), Equals, item.data,
- Commentf("Failed on item %d", i))
- }
-}
-
-func (s *S) TestUnmarshalStructSampleItems(c *C) {
- for _, item := range structSampleItems {
- testUnmarshal(c, item.data, item.obj)
- }
-}
-
-func (s *S) Test64bitInt(c *C) {
- var i int64 = (1 << 31)
- if int(i) > 0 {
- data, err := bson.Marshal(bson.M{"i": int(i)})
- c.Assert(err, IsNil)
- c.Assert(string(data), Equals, wrapInDoc("\x12i\x00\x00\x00\x00\x80\x00\x00\x00\x00"))
-
- var result struct{ I int }
- err = bson.Unmarshal(data, &result)
- c.Assert(err, IsNil)
- c.Assert(int64(result.I), Equals, i)
- }
-}
-
-// --------------------------------------------------------------------------
-// Generic two-way struct marshaling tests.
-
-var bytevar = byte(8)
-var byteptr = &bytevar
-
-var structItems = []testItemType{
- {&struct{ Ptr *byte }{nil},
- "\x0Aptr\x00"},
- {&struct{ Ptr *byte }{&bytevar},
- "\x10ptr\x00\x08\x00\x00\x00"},
- {&struct{ Ptr **byte }{&byteptr},
- "\x10ptr\x00\x08\x00\x00\x00"},
- {&struct{ Byte byte }{8},
- "\x10byte\x00\x08\x00\x00\x00"},
- {&struct{ Byte byte }{0},
- "\x10byte\x00\x00\x00\x00\x00"},
- {&struct {
- V byte "Tag"
- }{8},
- "\x10Tag\x00\x08\x00\x00\x00"},
- {&struct {
- V *struct {
- Byte byte
- }
- }{&struct{ Byte byte }{8}},
- "\x03v\x00" + "\x0f\x00\x00\x00\x10byte\x00\b\x00\x00\x00\x00"},
- {&struct{ priv byte }{}, ""},
-
- // The order of the dumped fields should be the same in the struct.
- {&struct{ A, C, B, D, F, E *byte }{},
- "\x0Aa\x00\x0Ac\x00\x0Ab\x00\x0Ad\x00\x0Af\x00\x0Ae\x00"},
-
- {&struct{ V bson.Raw }{bson.Raw{0x03, []byte("\x0f\x00\x00\x00\x10byte\x00\b\x00\x00\x00\x00")}},
- "\x03v\x00" + "\x0f\x00\x00\x00\x10byte\x00\b\x00\x00\x00\x00"},
- {&struct{ V bson.Raw }{bson.Raw{0x10, []byte("\x00\x00\x00\x00")}},
- "\x10v\x00" + "\x00\x00\x00\x00"},
-
- // Byte arrays.
- {&struct{ V [2]byte }{[2]byte{'y', 'o'}},
- "\x05v\x00\x02\x00\x00\x00\x00yo"},
-}
-
-func (s *S) TestMarshalStructItems(c *C) {
- for i, item := range structItems {
- data, err := bson.Marshal(item.obj)
- c.Assert(err, IsNil)
- c.Assert(string(data), Equals, wrapInDoc(item.data),
- Commentf("Failed on item %d", i))
- }
-}
-
-func (s *S) TestUnmarshalStructItems(c *C) {
- for _, item := range structItems {
- testUnmarshal(c, wrapInDoc(item.data), item.obj)
- }
-}
-
-func (s *S) TestUnmarshalRawStructItems(c *C) {
- for i, item := range structItems {
- raw := bson.Raw{0x03, []byte(wrapInDoc(item.data))}
- zero := makeZeroDoc(item.obj)
- err := raw.Unmarshal(zero)
- c.Assert(err, IsNil)
- c.Assert(zero, DeepEquals, item.obj, Commentf("Failed on item %d: %#v", i, item))
- }
-}
-
-func (s *S) TestUnmarshalRawNil(c *C) {
- // Regression test: shouldn't try to nil out the pointer itself,
- // as it's not settable.
- raw := bson.Raw{0x0A, []byte{}}
- err := raw.Unmarshal(&struct{}{})
- c.Assert(err, IsNil)
-}
-
-// --------------------------------------------------------------------------
-// One-way marshaling tests.
-
-type dOnIface struct {
- D interface{}
-}
-
-type ignoreField struct {
- Before string
- Ignore string `bson:"-"`
- After string
-}
-
-var marshalItems = []testItemType{
- // Ordered document dump. Will unmarshal as a dictionary by default.
- {bson.D{{"a", nil}, {"c", nil}, {"b", nil}, {"d", nil}, {"f", nil}, {"e", true}},
- "\x0Aa\x00\x0Ac\x00\x0Ab\x00\x0Ad\x00\x0Af\x00\x08e\x00\x01"},
- {MyD{{"a", nil}, {"c", nil}, {"b", nil}, {"d", nil}, {"f", nil}, {"e", true}},
- "\x0Aa\x00\x0Ac\x00\x0Ab\x00\x0Ad\x00\x0Af\x00\x08e\x00\x01"},
- {&dOnIface{bson.D{{"a", nil}, {"c", nil}, {"b", nil}, {"d", true}}},
- "\x03d\x00" + wrapInDoc("\x0Aa\x00\x0Ac\x00\x0Ab\x00\x08d\x00\x01")},
-
- {bson.RawD{{"a", bson.Raw{0x0A, nil}}, {"c", bson.Raw{0x0A, nil}}, {"b", bson.Raw{0x08, []byte{0x01}}}},
- "\x0Aa\x00" + "\x0Ac\x00" + "\x08b\x00\x01"},
- {MyRawD{{"a", bson.Raw{0x0A, nil}}, {"c", bson.Raw{0x0A, nil}}, {"b", bson.Raw{0x08, []byte{0x01}}}},
- "\x0Aa\x00" + "\x0Ac\x00" + "\x08b\x00\x01"},
- {&dOnIface{bson.RawD{{"a", bson.Raw{0x0A, nil}}, {"c", bson.Raw{0x0A, nil}}, {"b", bson.Raw{0x08, []byte{0x01}}}}},
- "\x03d\x00" + wrapInDoc("\x0Aa\x00"+"\x0Ac\x00"+"\x08b\x00\x01")},
-
- {&ignoreField{"before", "ignore", "after"},
- "\x02before\x00\a\x00\x00\x00before\x00\x02after\x00\x06\x00\x00\x00after\x00"},
-
- // Marshalling a Raw document does nothing.
- {bson.Raw{0x03, []byte(wrapInDoc("anything"))},
- "anything"},
- {bson.Raw{Data: []byte(wrapInDoc("anything"))},
- "anything"},
-}
-
-func (s *S) TestMarshalOneWayItems(c *C) {
- for _, item := range marshalItems {
- data, err := bson.Marshal(item.obj)
- c.Assert(err, IsNil)
- c.Assert(string(data), Equals, wrapInDoc(item.data))
- }
-}
-
-// --------------------------------------------------------------------------
-// One-way unmarshaling tests.
-
-var unmarshalItems = []testItemType{
- // Field is private. Should not attempt to unmarshal it.
- {&struct{ priv byte }{},
- "\x10priv\x00\x08\x00\x00\x00"},
-
- // Wrong casing. Field names are lowercased.
- {&struct{ Byte byte }{},
- "\x10Byte\x00\x08\x00\x00\x00"},
-
- // Ignore non-existing field.
- {&struct{ Byte byte }{9},
- "\x10boot\x00\x08\x00\x00\x00" + "\x10byte\x00\x09\x00\x00\x00"},
-
- // Do not unmarshal on ignored field.
- {&ignoreField{"before", "", "after"},
- "\x02before\x00\a\x00\x00\x00before\x00" +
- "\x02-\x00\a\x00\x00\x00ignore\x00" +
- "\x02after\x00\x06\x00\x00\x00after\x00"},
-
- // Ignore unsuitable types silently.
- {map[string]string{"str": "s"},
- "\x02str\x00\x02\x00\x00\x00s\x00" + "\x10int\x00\x01\x00\x00\x00"},
- {map[string][]int{"array": []int{5, 9}},
- "\x04array\x00" + wrapInDoc("\x100\x00\x05\x00\x00\x00"+"\x021\x00\x02\x00\x00\x00s\x00"+"\x102\x00\x09\x00\x00\x00")},
-
- // Wrong type. Shouldn't init pointer.
- {&struct{ Str *byte }{},
- "\x02str\x00\x02\x00\x00\x00s\x00"},
- {&struct{ Str *struct{ Str string } }{},
- "\x02str\x00\x02\x00\x00\x00s\x00"},
-
- // Ordered document.
- {&struct{ bson.D }{bson.D{{"a", nil}, {"c", nil}, {"b", nil}, {"d", true}}},
- "\x03d\x00" + wrapInDoc("\x0Aa\x00\x0Ac\x00\x0Ab\x00\x08d\x00\x01")},
-
- // Raw document.
- {&bson.Raw{0x03, []byte(wrapInDoc("\x10byte\x00\x08\x00\x00\x00"))},
- "\x10byte\x00\x08\x00\x00\x00"},
-
- // RawD document.
- {&struct{ bson.RawD }{bson.RawD{{"a", bson.Raw{0x0A, []byte{}}}, {"c", bson.Raw{0x0A, []byte{}}}, {"b", bson.Raw{0x08, []byte{0x01}}}}},
- "\x03rawd\x00" + wrapInDoc("\x0Aa\x00\x0Ac\x00\x08b\x00\x01")},
-
- // Decode old binary.
- {bson.M{"_": []byte("old")},
- "\x05_\x00\x07\x00\x00\x00\x02\x03\x00\x00\x00old"},
-
- // Decode old binary without length. According to the spec, this shouldn't happen.
- {bson.M{"_": []byte("old")},
- "\x05_\x00\x03\x00\x00\x00\x02old"},
-
- // Decode a doc within a doc in to a slice within a doc; shouldn't error
- {&struct{ Foo []string }{},
- "\x03\x66\x6f\x6f\x00\x05\x00\x00\x00\x00"},
-}
-
-func (s *S) TestUnmarshalOneWayItems(c *C) {
- for _, item := range unmarshalItems {
- testUnmarshal(c, wrapInDoc(item.data), item.obj)
- }
-}
-
-func (s *S) TestUnmarshalNilInStruct(c *C) {
- // Nil is the default value, so we need to ensure it's indeed being set.
- b := byte(1)
- v := &struct{ Ptr *byte }{&b}
- err := bson.Unmarshal([]byte(wrapInDoc("\x0Aptr\x00")), v)
- c.Assert(err, IsNil)
- c.Assert(v, DeepEquals, &struct{ Ptr *byte }{nil})
-}
-
-// --------------------------------------------------------------------------
-// Marshalling error cases.
-
-type structWithDupKeys struct {
- Name byte
- Other byte "name" // Tag should precede.
-}
-
-var marshalErrorItems = []testItemType{
- {bson.M{"": uint64(1 << 63)},
- "BSON has no uint64 type, and value is too large to fit correctly in an int64"},
- {bson.M{"": bson.ObjectId("tooshort")},
- "ObjectIDs must be exactly 12 bytes long \\(got 8\\)"},
- {int64(123),
- "Can't marshal int64 as a BSON document"},
- {bson.M{"": 1i},
- "Can't marshal complex128 in a BSON document"},
- {&structWithDupKeys{},
- "Duplicated key 'name' in struct bson_test.structWithDupKeys"},
- {bson.Raw{0xA, []byte{}},
- "Attempted to marshal Raw kind 10 as a document"},
- {bson.Raw{0x3, []byte{}},
- "Attempted to marshal empty Raw document"},
- {bson.M{"w": bson.Raw{0x3, []byte{}}},
- "Attempted to marshal empty Raw document"},
- {&inlineCantPtr{&struct{ A, B int }{1, 2}},
- "Option ,inline needs a struct value or map field"},
- {&inlineDupName{1, struct{ A, B int }{2, 3}},
- "Duplicated key 'a' in struct bson_test.inlineDupName"},
- {&inlineDupMap{},
- "Multiple ,inline maps in struct bson_test.inlineDupMap"},
- {&inlineBadKeyMap{},
- "Option ,inline needs a map with string keys in struct bson_test.inlineBadKeyMap"},
- {&inlineMap{A: 1, M: map[string]interface{}{"a": 1}},
- `Can't have key "a" in inlined map; conflicts with struct field`},
-}
-
-func (s *S) TestMarshalErrorItems(c *C) {
- for _, item := range marshalErrorItems {
- data, err := bson.Marshal(item.obj)
- c.Assert(err, ErrorMatches, item.data)
- c.Assert(data, IsNil)
- }
-}
-
-// --------------------------------------------------------------------------
-// Unmarshalling error cases.
-
-type unmarshalErrorType struct {
- obj interface{}
- data string
- error string
-}
-
-var unmarshalErrorItems = []unmarshalErrorType{
- // Tag name conflicts with existing parameter.
- {&structWithDupKeys{},
- "\x10name\x00\x08\x00\x00\x00",
- "Duplicated key 'name' in struct bson_test.structWithDupKeys"},
-
- // Non-string map key.
- {map[int]interface{}{},
- "\x10name\x00\x08\x00\x00\x00",
- "BSON map must have string keys. Got: map\\[int\\]interface \\{\\}"},
-
- {nil,
- "\xEEname\x00",
- "Unknown element kind \\(0xEE\\)"},
-
- {struct{ Name bool }{},
- "\x10name\x00\x08\x00\x00\x00",
- "Unmarshal can't deal with struct values. Use a pointer."},
-
- {123,
- "\x10name\x00\x08\x00\x00\x00",
- "Unmarshal needs a map or a pointer to a struct."},
-
- {nil,
- "\x08\x62\x00\x02",
- "encoded boolean must be 1 or 0, found 2"},
-}
-
-func (s *S) TestUnmarshalErrorItems(c *C) {
- for _, item := range unmarshalErrorItems {
- data := []byte(wrapInDoc(item.data))
- var value interface{}
- switch reflect.ValueOf(item.obj).Kind() {
- case reflect.Map, reflect.Ptr:
- value = makeZeroDoc(item.obj)
- case reflect.Invalid:
- value = bson.M{}
- default:
- value = item.obj
- }
- err := bson.Unmarshal(data, value)
- c.Assert(err, ErrorMatches, item.error)
- }
-}
-
-type unmarshalRawErrorType struct {
- obj interface{}
- raw bson.Raw
- error string
-}
-
-var unmarshalRawErrorItems = []unmarshalRawErrorType{
- // Tag name conflicts with existing parameter.
- {&structWithDupKeys{},
- bson.Raw{0x03, []byte("\x10byte\x00\x08\x00\x00\x00")},
- "Duplicated key 'name' in struct bson_test.structWithDupKeys"},
-
- {&struct{}{},
- bson.Raw{0xEE, []byte{}},
- "Unknown element kind \\(0xEE\\)"},
-
- {struct{ Name bool }{},
- bson.Raw{0x10, []byte("\x08\x00\x00\x00")},
- "Raw Unmarshal can't deal with struct values. Use a pointer."},
-
- {123,
- bson.Raw{0x10, []byte("\x08\x00\x00\x00")},
- "Raw Unmarshal needs a map or a valid pointer."},
-}
-
-func (s *S) TestUnmarshalRawErrorItems(c *C) {
- for i, item := range unmarshalRawErrorItems {
- err := item.raw.Unmarshal(item.obj)
- c.Assert(err, ErrorMatches, item.error, Commentf("Failed on item %d: %#v\n", i, item))
- }
-}
-
-var corruptedData = []string{
- "\x04\x00\x00\x00\x00", // Document shorter than minimum
- "\x06\x00\x00\x00\x00", // Not enough data
- "\x05\x00\x00", // Broken length
- "\x05\x00\x00\x00\xff", // Corrupted termination
- "\x0A\x00\x00\x00\x0Aooop\x00", // Unfinished C string
-
- // Array end past end of string (s[2]=0x07 is correct)
- wrapInDoc("\x04\x00\x09\x00\x00\x00\x0A\x00\x00"),
-
- // Array end within string, but past acceptable.
- wrapInDoc("\x04\x00\x08\x00\x00\x00\x0A\x00\x00"),
-
- // Document end within string, but past acceptable.
- wrapInDoc("\x03\x00\x08\x00\x00\x00\x0A\x00\x00"),
-
- // String with corrupted end.
- wrapInDoc("\x02\x00\x03\x00\x00\x00yo\xFF"),
-
- // String with negative length (issue #116).
- "\x0c\x00\x00\x00\x02x\x00\xff\xff\xff\xff\x00",
-
- // String with zero length (must include trailing '\x00')
- "\x0c\x00\x00\x00\x02x\x00\x00\x00\x00\x00\x00",
-
- // Binary with negative length.
- "\r\x00\x00\x00\x05x\x00\xff\xff\xff\xff\x00\x00",
-}
-
-func (s *S) TestUnmarshalMapDocumentTooShort(c *C) {
- for _, data := range corruptedData {
- err := bson.Unmarshal([]byte(data), bson.M{})
- c.Assert(err, ErrorMatches, "Document is corrupted")
-
- err = bson.Unmarshal([]byte(data), &struct{}{})
- c.Assert(err, ErrorMatches, "Document is corrupted")
- }
-}
-
-// --------------------------------------------------------------------------
-// Setter test cases.
-
-var setterResult = map[string]error{}
-
-type setterType struct {
- received interface{}
-}
-
-func (o *setterType) SetBSON(raw bson.Raw) error {
- err := raw.Unmarshal(&o.received)
- if err != nil {
- panic("The panic:" + err.Error())
- }
- if s, ok := o.received.(string); ok {
- if result, ok := setterResult[s]; ok {
- return result
- }
- }
- return nil
-}
-
-type ptrSetterDoc struct {
- Field *setterType "_"
-}
-
-type valSetterDoc struct {
- Field setterType "_"
-}
-
-func (s *S) TestUnmarshalAllItemsWithPtrSetter(c *C) {
- for _, item := range allItems {
- for i := 0; i != 2; i++ {
- var field *setterType
- if i == 0 {
- obj := &ptrSetterDoc{}
- err := bson.Unmarshal([]byte(wrapInDoc(item.data)), obj)
- c.Assert(err, IsNil)
- field = obj.Field
- } else {
- obj := &valSetterDoc{}
- err := bson.Unmarshal([]byte(wrapInDoc(item.data)), obj)
- c.Assert(err, IsNil)
- field = &obj.Field
- }
- if item.data == "" {
- // Nothing to unmarshal. Should be untouched.
- if i == 0 {
- c.Assert(field, IsNil)
- } else {
- c.Assert(field.received, IsNil)
- }
- } else {
- expected := item.obj.(bson.M)["_"]
- c.Assert(field, NotNil, Commentf("Pointer not initialized (%#v)", expected))
- c.Assert(field.received, DeepEquals, expected)
- }
- }
- }
-}
-
-func (s *S) TestUnmarshalWholeDocumentWithSetter(c *C) {
- obj := &setterType{}
- err := bson.Unmarshal([]byte(sampleItems[0].data), obj)
- c.Assert(err, IsNil)
- c.Assert(obj.received, DeepEquals, bson.M{"hello": "world"})
-}
-
-func (s *S) TestUnmarshalSetterOmits(c *C) {
- setterResult["2"] = &bson.TypeError{}
- setterResult["4"] = &bson.TypeError{}
- defer func() {
- delete(setterResult, "2")
- delete(setterResult, "4")
- }()
-
- m := map[string]*setterType{}
- data := wrapInDoc("\x02abc\x00\x02\x00\x00\x001\x00" +
- "\x02def\x00\x02\x00\x00\x002\x00" +
- "\x02ghi\x00\x02\x00\x00\x003\x00" +
- "\x02jkl\x00\x02\x00\x00\x004\x00")
- err := bson.Unmarshal([]byte(data), m)
- c.Assert(err, IsNil)
- c.Assert(m["abc"], NotNil)
- c.Assert(m["def"], IsNil)
- c.Assert(m["ghi"], NotNil)
- c.Assert(m["jkl"], IsNil)
-
- c.Assert(m["abc"].received, Equals, "1")
- c.Assert(m["ghi"].received, Equals, "3")
-}
-
-func (s *S) TestUnmarshalSetterErrors(c *C) {
- boom := errors.New("BOOM")
- setterResult["2"] = boom
- defer delete(setterResult, "2")
-
- m := map[string]*setterType{}
- data := wrapInDoc("\x02abc\x00\x02\x00\x00\x001\x00" +
- "\x02def\x00\x02\x00\x00\x002\x00" +
- "\x02ghi\x00\x02\x00\x00\x003\x00")
- err := bson.Unmarshal([]byte(data), m)
- c.Assert(err, Equals, boom)
- c.Assert(m["abc"], NotNil)
- c.Assert(m["def"], IsNil)
- c.Assert(m["ghi"], IsNil)
-
- c.Assert(m["abc"].received, Equals, "1")
-}
-
-func (s *S) TestDMap(c *C) {
- d := bson.D{{"a", 1}, {"b", 2}}
- c.Assert(d.Map(), DeepEquals, bson.M{"a": 1, "b": 2})
-}
-
-func (s *S) TestUnmarshalSetterSetZero(c *C) {
- setterResult["foo"] = bson.SetZero
- defer delete(setterResult, "field")
-
- data, err := bson.Marshal(bson.M{"field": "foo"})
- c.Assert(err, IsNil)
-
- m := map[string]*setterType{}
- err = bson.Unmarshal([]byte(data), m)
- c.Assert(err, IsNil)
-
- value, ok := m["field"]
- c.Assert(ok, Equals, true)
- c.Assert(value, IsNil)
-}
-
-// --------------------------------------------------------------------------
-// Getter test cases.
-
-type typeWithGetter struct {
- result interface{}
- err error
-}
-
-func (t *typeWithGetter) GetBSON() (interface{}, error) {
- if t == nil {
- return "", nil
- }
- return t.result, t.err
-}
-
-type docWithGetterField struct {
- Field *typeWithGetter "_"
-}
-
-func (s *S) TestMarshalAllItemsWithGetter(c *C) {
- for i, item := range allItems {
- if item.data == "" {
- continue
- }
- obj := &docWithGetterField{}
- obj.Field = &typeWithGetter{result: item.obj.(bson.M)["_"]}
- data, err := bson.Marshal(obj)
- c.Assert(err, IsNil)
- c.Assert(string(data), Equals, wrapInDoc(item.data),
- Commentf("Failed on item #%d", i))
- }
-}
-
-func (s *S) TestMarshalWholeDocumentWithGetter(c *C) {
- obj := &typeWithGetter{result: sampleItems[0].obj}
- data, err := bson.Marshal(obj)
- c.Assert(err, IsNil)
- c.Assert(string(data), Equals, sampleItems[0].data)
-}
-
-func (s *S) TestGetterErrors(c *C) {
- e := errors.New("oops")
-
- obj1 := &docWithGetterField{}
- obj1.Field = &typeWithGetter{sampleItems[0].obj, e}
- data, err := bson.Marshal(obj1)
- c.Assert(err, ErrorMatches, "oops")
- c.Assert(data, IsNil)
-
- obj2 := &typeWithGetter{sampleItems[0].obj, e}
- data, err = bson.Marshal(obj2)
- c.Assert(err, ErrorMatches, "oops")
- c.Assert(data, IsNil)
-}
-
-type intGetter int64
-
-func (t intGetter) GetBSON() (interface{}, error) {
- return int64(t), nil
-}
-
-type typeWithIntGetter struct {
- V intGetter ",minsize"
-}
-
-func (s *S) TestMarshalShortWithGetter(c *C) {
- obj := typeWithIntGetter{42}
- data, err := bson.Marshal(obj)
- c.Assert(err, IsNil)
- m := bson.M{}
- err = bson.Unmarshal(data, m)
- c.Assert(err, IsNil)
- c.Assert(m["v"], Equals, 42)
-}
-
-func (s *S) TestMarshalWithGetterNil(c *C) {
- obj := docWithGetterField{}
- data, err := bson.Marshal(obj)
- c.Assert(err, IsNil)
- m := bson.M{}
- err = bson.Unmarshal(data, m)
- c.Assert(err, IsNil)
- c.Assert(m, DeepEquals, bson.M{"_": ""})
-}
-
-// --------------------------------------------------------------------------
-// Cross-type conversion tests.
-
-type crossTypeItem struct {
- obj1 interface{}
- obj2 interface{}
-}
-
-type condStr struct {
- V string ",omitempty"
-}
-type condStrNS struct {
- V string `a:"A" bson:",omitempty" b:"B"`
-}
-type condBool struct {
- V bool ",omitempty"
-}
-type condInt struct {
- V int ",omitempty"
-}
-type condUInt struct {
- V uint ",omitempty"
-}
-type condFloat struct {
- V float64 ",omitempty"
-}
-type condIface struct {
- V interface{} ",omitempty"
-}
-type condPtr struct {
- V *bool ",omitempty"
-}
-type condSlice struct {
- V []string ",omitempty"
-}
-type condMap struct {
- V map[string]int ",omitempty"
-}
-type namedCondStr struct {
- V string "myv,omitempty"
-}
-type condTime struct {
- V time.Time ",omitempty"
-}
-type condStruct struct {
- V struct{ A []int } ",omitempty"
-}
-type condRaw struct {
- V bson.Raw ",omitempty"
-}
-
-type shortInt struct {
- V int64 ",minsize"
-}
-type shortUint struct {
- V uint64 ",minsize"
-}
-type shortIface struct {
- V interface{} ",minsize"
-}
-type shortPtr struct {
- V *int64 ",minsize"
-}
-type shortNonEmptyInt struct {
- V int64 ",minsize,omitempty"
-}
-
-type inlineInt struct {
- V struct{ A, B int } ",inline"
-}
-type inlineCantPtr struct {
- V *struct{ A, B int } ",inline"
-}
-type inlineDupName struct {
- A int
- V struct{ A, B int } ",inline"
-}
-type inlineMap struct {
- A int
- M map[string]interface{} ",inline"
-}
-type inlineMapInt struct {
- A int
- M map[string]int ",inline"
-}
-type inlineMapMyM struct {
- A int
- M MyM ",inline"
-}
-type inlineDupMap struct {
- M1 map[string]interface{} ",inline"
- M2 map[string]interface{} ",inline"
-}
-type inlineBadKeyMap struct {
- M map[int]int ",inline"
-}
-type inlineUnexported struct {
- M map[string]interface{} ",inline"
- unexported ",inline"
-}
-type unexported struct {
- A int
-}
-
-type getterSetterD bson.D
-
-func (s getterSetterD) GetBSON() (interface{}, error) {
- if len(s) == 0 {
- return bson.D{}, nil
- }
- return bson.D(s[:len(s)-1]), nil
-}
-
-func (s *getterSetterD) SetBSON(raw bson.Raw) error {
- var doc bson.D
- err := raw.Unmarshal(&doc)
- doc = append(doc, bson.DocElem{"suffix", true})
- *s = getterSetterD(doc)
- return err
-}
-
-type getterSetterInt int
-
-func (i getterSetterInt) GetBSON() (interface{}, error) {
- return bson.D{{"a", int(i)}}, nil
-}
-
-func (i *getterSetterInt) SetBSON(raw bson.Raw) error {
- var doc struct{ A int }
- err := raw.Unmarshal(&doc)
- *i = getterSetterInt(doc.A)
- return err
-}
-
-type ifaceType interface {
- Hello()
-}
-
-type ifaceSlice []ifaceType
-
-func (s *ifaceSlice) SetBSON(raw bson.Raw) error {
- var ns []int
- if err := raw.Unmarshal(&ns); err != nil {
- return err
- }
- *s = make(ifaceSlice, ns[0])
- return nil
-}
-
-func (s ifaceSlice) GetBSON() (interface{}, error) {
- return []int{len(s)}, nil
-}
-
-type (
- MyString string
- MyBytes []byte
- MyBool bool
- MyD []bson.DocElem
- MyRawD []bson.RawDocElem
- MyM map[string]interface{}
-)
-
-var (
- truevar = true
- falsevar = false
-
- int64var = int64(42)
- int64ptr = &int64var
- intvar = int(42)
- intptr = &intvar
-
- gsintvar = getterSetterInt(42)
-)
-
-func parseURL(s string) *url.URL {
- u, err := url.Parse(s)
- if err != nil {
- panic(err)
- }
- return u
-}
-
-// That's a pretty fun test. It will dump the first item, generate a zero
-// value equivalent to the second one, load the dumped data onto it, and then
-// verify that the resulting value is deep-equal to the untouched second value.
-// Then, it will do the same in the *opposite* direction!
-var twoWayCrossItems = []crossTypeItem{
- // int<=>int
- {&struct{ I int }{42}, &struct{ I int8 }{42}},
- {&struct{ I int }{42}, &struct{ I int32 }{42}},
- {&struct{ I int }{42}, &struct{ I int64 }{42}},
- {&struct{ I int8 }{42}, &struct{ I int32 }{42}},
- {&struct{ I int8 }{42}, &struct{ I int64 }{42}},
- {&struct{ I int32 }{42}, &struct{ I int64 }{42}},
-
- // uint<=>uint
- {&struct{ I uint }{42}, &struct{ I uint8 }{42}},
- {&struct{ I uint }{42}, &struct{ I uint32 }{42}},
- {&struct{ I uint }{42}, &struct{ I uint64 }{42}},
- {&struct{ I uint8 }{42}, &struct{ I uint32 }{42}},
- {&struct{ I uint8 }{42}, &struct{ I uint64 }{42}},
- {&struct{ I uint32 }{42}, &struct{ I uint64 }{42}},
-
- // float32<=>float64
- {&struct{ I float32 }{42}, &struct{ I float64 }{42}},
-
- // int<=>uint
- {&struct{ I uint }{42}, &struct{ I int }{42}},
- {&struct{ I uint }{42}, &struct{ I int8 }{42}},
- {&struct{ I uint }{42}, &struct{ I int32 }{42}},
- {&struct{ I uint }{42}, &struct{ I int64 }{42}},
- {&struct{ I uint8 }{42}, &struct{ I int }{42}},
- {&struct{ I uint8 }{42}, &struct{ I int8 }{42}},
- {&struct{ I uint8 }{42}, &struct{ I int32 }{42}},
- {&struct{ I uint8 }{42}, &struct{ I int64 }{42}},
- {&struct{ I uint32 }{42}, &struct{ I int }{42}},
- {&struct{ I uint32 }{42}, &struct{ I int8 }{42}},
- {&struct{ I uint32 }{42}, &struct{ I int32 }{42}},
- {&struct{ I uint32 }{42}, &struct{ I int64 }{42}},
- {&struct{ I uint64 }{42}, &struct{ I int }{42}},
- {&struct{ I uint64 }{42}, &struct{ I int8 }{42}},
- {&struct{ I uint64 }{42}, &struct{ I int32 }{42}},
- {&struct{ I uint64 }{42}, &struct{ I int64 }{42}},
-
- // int <=> float
- {&struct{ I int }{42}, &struct{ I float64 }{42}},
-
- // int <=> bool
- {&struct{ I int }{1}, &struct{ I bool }{true}},
- {&struct{ I int }{0}, &struct{ I bool }{false}},
-
- // uint <=> float64
- {&struct{ I uint }{42}, &struct{ I float64 }{42}},
-
- // uint <=> bool
- {&struct{ I uint }{1}, &struct{ I bool }{true}},
- {&struct{ I uint }{0}, &struct{ I bool }{false}},
-
- // float64 <=> bool
- {&struct{ I float64 }{1}, &struct{ I bool }{true}},
- {&struct{ I float64 }{0}, &struct{ I bool }{false}},
-
- // string <=> string and string <=> []byte
- {&struct{ S []byte }{[]byte("abc")}, &struct{ S string }{"abc"}},
- {&struct{ S []byte }{[]byte("def")}, &struct{ S bson.Symbol }{"def"}},
- {&struct{ S string }{"ghi"}, &struct{ S bson.Symbol }{"ghi"}},
-
- // map <=> struct
- {&struct {
- A struct {
- B, C int
- }
- }{struct{ B, C int }{1, 2}},
- map[string]map[string]int{"a": map[string]int{"b": 1, "c": 2}}},
-
- {&struct{ A bson.Symbol }{"abc"}, map[string]string{"a": "abc"}},
- {&struct{ A bson.Symbol }{"abc"}, map[string][]byte{"a": []byte("abc")}},
- {&struct{ A []byte }{[]byte("abc")}, map[string]string{"a": "abc"}},
- {&struct{ A uint }{42}, map[string]int{"a": 42}},
- {&struct{ A uint }{42}, map[string]float64{"a": 42}},
- {&struct{ A uint }{1}, map[string]bool{"a": true}},
- {&struct{ A int }{42}, map[string]uint{"a": 42}},
- {&struct{ A int }{42}, map[string]float64{"a": 42}},
- {&struct{ A int }{1}, map[string]bool{"a": true}},
- {&struct{ A float64 }{42}, map[string]float32{"a": 42}},
- {&struct{ A float64 }{42}, map[string]int{"a": 42}},
- {&struct{ A float64 }{42}, map[string]uint{"a": 42}},
- {&struct{ A float64 }{1}, map[string]bool{"a": true}},
- {&struct{ A bool }{true}, map[string]int{"a": 1}},
- {&struct{ A bool }{true}, map[string]uint{"a": 1}},
- {&struct{ A bool }{true}, map[string]float64{"a": 1}},
- {&struct{ A **byte }{&byteptr}, map[string]byte{"a": 8}},
-
- // url.URL <=> string
- {&struct{ URL *url.URL }{parseURL("h://e.c/p")}, map[string]string{"url": "h://e.c/p"}},
- {&struct{ URL url.URL }{*parseURL("h://e.c/p")}, map[string]string{"url": "h://e.c/p"}},
-
- // Slices
- {&struct{ S []int }{[]int{1, 2, 3}}, map[string][]int{"s": []int{1, 2, 3}}},
- {&struct{ S *[]int }{&[]int{1, 2, 3}}, map[string][]int{"s": []int{1, 2, 3}}},
-
- // Conditionals
- {&condBool{true}, map[string]bool{"v": true}},
- {&condBool{}, map[string]bool{}},
- {&condInt{1}, map[string]int{"v": 1}},
- {&condInt{}, map[string]int{}},
- {&condUInt{1}, map[string]uint{"v": 1}},
- {&condUInt{}, map[string]uint{}},
- {&condFloat{}, map[string]int{}},
- {&condStr{"yo"}, map[string]string{"v": "yo"}},
- {&condStr{}, map[string]string{}},
- {&condStrNS{"yo"}, map[string]string{"v": "yo"}},
- {&condStrNS{}, map[string]string{}},
- {&condSlice{[]string{"yo"}}, map[string][]string{"v": []string{"yo"}}},
- {&condSlice{}, map[string][]string{}},
- {&condMap{map[string]int{"k": 1}}, bson.M{"v": bson.M{"k": 1}}},
- {&condMap{}, map[string][]string{}},
- {&condIface{"yo"}, map[string]string{"v": "yo"}},
- {&condIface{""}, map[string]string{"v": ""}},
- {&condIface{}, map[string]string{}},
- {&condPtr{&truevar}, map[string]bool{"v": true}},
- {&condPtr{&falsevar}, map[string]bool{"v": false}},
- {&condPtr{}, map[string]string{}},
-
- {&condTime{time.Unix(123456789, 123e6)}, map[string]time.Time{"v": time.Unix(123456789, 123e6)}},
- {&condTime{}, map[string]string{}},
-
- {&condStruct{struct{ A []int }{[]int{1}}}, bson.M{"v": bson.M{"a": []interface{}{1}}}},
- {&condStruct{struct{ A []int }{}}, bson.M{}},
-
- {&condRaw{bson.Raw{Kind: 0x0A, Data: []byte{}}}, bson.M{"v": nil}},
- {&condRaw{bson.Raw{Kind: 0x00}}, bson.M{}},
-
- {&namedCondStr{"yo"}, map[string]string{"myv": "yo"}},
- {&namedCondStr{}, map[string]string{}},
-
- {&shortInt{1}, map[string]interface{}{"v": 1}},
- {&shortInt{1 << 30}, map[string]interface{}{"v": 1 << 30}},
- {&shortInt{1 << 31}, map[string]interface{}{"v": int64(1 << 31)}},
- {&shortUint{1 << 30}, map[string]interface{}{"v": 1 << 30}},
- {&shortUint{1 << 31}, map[string]interface{}{"v": int64(1 << 31)}},
- {&shortIface{int64(1) << 31}, map[string]interface{}{"v": int64(1 << 31)}},
- {&shortPtr{int64ptr}, map[string]interface{}{"v": intvar}},
-
- {&shortNonEmptyInt{1}, map[string]interface{}{"v": 1}},
- {&shortNonEmptyInt{1 << 31}, map[string]interface{}{"v": int64(1 << 31)}},
- {&shortNonEmptyInt{}, map[string]interface{}{}},
-
- {&inlineInt{struct{ A, B int }{1, 2}}, map[string]interface{}{"a": 1, "b": 2}},
- {&inlineMap{A: 1, M: map[string]interface{}{"b": 2}}, map[string]interface{}{"a": 1, "b": 2}},
- {&inlineMap{A: 1, M: nil}, map[string]interface{}{"a": 1}},
- {&inlineMapInt{A: 1, M: map[string]int{"b": 2}}, map[string]int{"a": 1, "b": 2}},
- {&inlineMapInt{A: 1, M: nil}, map[string]int{"a": 1}},
- {&inlineMapMyM{A: 1, M: MyM{"b": MyM{"c": 3}}}, map[string]interface{}{"a": 1, "b": map[string]interface{}{"c": 3}}},
- {&inlineUnexported{M: map[string]interface{}{"b": 1}, unexported: unexported{A: 2}}, map[string]interface{}{"b": 1, "a": 2}},
-
- // []byte <=> Binary
- {&struct{ B []byte }{[]byte("abc")}, map[string]bson.Binary{"b": bson.Binary{Data: []byte("abc")}}},
-
- // []byte <=> MyBytes
- {&struct{ B MyBytes }{[]byte("abc")}, map[string]string{"b": "abc"}},
- {&struct{ B MyBytes }{[]byte{}}, map[string]string{"b": ""}},
- {&struct{ B MyBytes }{}, map[string]bool{}},
- {&struct{ B []byte }{[]byte("abc")}, map[string]MyBytes{"b": []byte("abc")}},
-
- // bool <=> MyBool
- {&struct{ B MyBool }{true}, map[string]bool{"b": true}},
- {&struct{ B MyBool }{}, map[string]bool{"b": false}},
- {&struct{ B MyBool }{}, map[string]string{}},
- {&struct{ B bool }{}, map[string]MyBool{"b": false}},
-
- // arrays
- {&struct{ V [2]int }{[...]int{1, 2}}, map[string][2]int{"v": [2]int{1, 2}}},
- {&struct{ V [2]byte }{[...]byte{1, 2}}, map[string][2]byte{"v": [2]byte{1, 2}}},
-
- // zero time
- {&struct{ V time.Time }{}, map[string]interface{}{"v": time.Time{}}},
-
- // zero time + 1 second + 1 millisecond; overflows int64 as nanoseconds
- {&struct{ V time.Time }{time.Unix(-62135596799, 1e6).Local()},
- map[string]interface{}{"v": time.Unix(-62135596799, 1e6).Local()}},
-
- // bson.D <=> []DocElem
- {&bson.D{{"a", bson.D{{"b", 1}, {"c", 2}}}}, &bson.D{{"a", bson.D{{"b", 1}, {"c", 2}}}}},
- {&bson.D{{"a", bson.D{{"b", 1}, {"c", 2}}}}, &MyD{{"a", MyD{{"b", 1}, {"c", 2}}}}},
- {&struct{ V MyD }{MyD{{"a", 1}}}, &bson.D{{"v", bson.D{{"a", 1}}}}},
-
- // bson.RawD <=> []RawDocElem
- {&bson.RawD{{"a", bson.Raw{0x08, []byte{0x01}}}}, &bson.RawD{{"a", bson.Raw{0x08, []byte{0x01}}}}},
- {&bson.RawD{{"a", bson.Raw{0x08, []byte{0x01}}}}, &MyRawD{{"a", bson.Raw{0x08, []byte{0x01}}}}},
-
- // bson.M <=> map
- {bson.M{"a": bson.M{"b": 1, "c": 2}}, MyM{"a": MyM{"b": 1, "c": 2}}},
- {bson.M{"a": bson.M{"b": 1, "c": 2}}, map[string]interface{}{"a": map[string]interface{}{"b": 1, "c": 2}}},
-
- // bson.M <=> map[MyString]
- {bson.M{"a": bson.M{"b": 1, "c": 2}}, map[MyString]interface{}{"a": map[MyString]interface{}{"b": 1, "c": 2}}},
-
- // json.Number <=> int64, float64
- {&struct{ N json.Number }{"5"}, map[string]interface{}{"n": int64(5)}},
- {&struct{ N json.Number }{"5.05"}, map[string]interface{}{"n": 5.05}},
- {&struct{ N json.Number }{"9223372036854776000"}, map[string]interface{}{"n": float64(1 << 63)}},
-
- // bson.D <=> non-struct getter/setter
- {&bson.D{{"a", 1}}, &getterSetterD{{"a", 1}, {"suffix", true}}},
- {&bson.D{{"a", 42}}, &gsintvar},
-
- // Interface slice setter.
- {&struct{ V ifaceSlice }{ifaceSlice{nil, nil, nil}}, bson.M{"v": []interface{}{3}}},
-}
-
-// Same thing, but only one way (obj1 => obj2).
-var oneWayCrossItems = []crossTypeItem{
- // map <=> struct
- {map[string]interface{}{"a": 1, "b": "2", "c": 3}, map[string]int{"a": 1, "c": 3}},
-
- // inline map elides badly typed values
- {map[string]interface{}{"a": 1, "b": "2", "c": 3}, &inlineMapInt{A: 1, M: map[string]int{"c": 3}}},
-
- // Can't decode int into struct.
- {bson.M{"a": bson.M{"b": 2}}, &struct{ A bool }{}},
-
- // Would get decoded into a int32 too in the opposite direction.
- {&shortIface{int64(1) << 30}, map[string]interface{}{"v": 1 << 30}},
-
- // Ensure omitempty on struct with private fields works properly.
- {&struct {
- V struct{ v time.Time } ",omitempty"
- }{}, map[string]interface{}{}},
-
- // Attempt to marshal slice into RawD (issue #120).
- {bson.M{"x": []int{1, 2, 3}}, &struct{ X bson.RawD }{}},
-}
-
-func testCrossPair(c *C, dump interface{}, load interface{}) {
- c.Logf("Dump: %#v", dump)
- c.Logf("Load: %#v", load)
- zero := makeZeroDoc(load)
- data, err := bson.Marshal(dump)
- c.Assert(err, IsNil)
- c.Logf("Dumped: %#v", string(data))
- err = bson.Unmarshal(data, zero)
- c.Assert(err, IsNil)
- c.Logf("Loaded: %#v", zero)
- c.Assert(zero, DeepEquals, load)
-}
-
-func (s *S) TestTwoWayCrossPairs(c *C) {
- for _, item := range twoWayCrossItems {
- testCrossPair(c, item.obj1, item.obj2)
- testCrossPair(c, item.obj2, item.obj1)
- }
-}
-
-func (s *S) TestOneWayCrossPairs(c *C) {
- for _, item := range oneWayCrossItems {
- testCrossPair(c, item.obj1, item.obj2)
- }
-}
-
-// --------------------------------------------------------------------------
-// ObjectId hex representation test.
-
-func (s *S) TestObjectIdHex(c *C) {
- id := bson.ObjectIdHex("4d88e15b60f486e428412dc9")
- c.Assert(id.String(), Equals, `ObjectIdHex("4d88e15b60f486e428412dc9")`)
- c.Assert(id.Hex(), Equals, "4d88e15b60f486e428412dc9")
-}
-
-func (s *S) TestIsObjectIdHex(c *C) {
- test := []struct {
- id string
- valid bool
- }{
- {"4d88e15b60f486e428412dc9", true},
- {"4d88e15b60f486e428412dc", false},
- {"4d88e15b60f486e428412dc9e", false},
- {"4d88e15b60f486e428412dcx", false},
- }
- for _, t := range test {
- c.Assert(bson.IsObjectIdHex(t.id), Equals, t.valid)
- }
-}
-
-// --------------------------------------------------------------------------
-// ObjectId parts extraction tests.
-
-type objectIdParts struct {
- id bson.ObjectId
- timestamp int64
- machine []byte
- pid uint16
- counter int32
-}
-
-var objectIds = []objectIdParts{
- objectIdParts{
- bson.ObjectIdHex("4d88e15b60f486e428412dc9"),
- 1300816219,
- []byte{0x60, 0xf4, 0x86},
- 0xe428,
- 4271561,
- },
- objectIdParts{
- bson.ObjectIdHex("000000000000000000000000"),
- 0,
- []byte{0x00, 0x00, 0x00},
- 0x0000,
- 0,
- },
- objectIdParts{
- bson.ObjectIdHex("00000000aabbccddee000001"),
- 0,
- []byte{0xaa, 0xbb, 0xcc},
- 0xddee,
- 1,
- },
-}
-
-func (s *S) TestObjectIdPartsExtraction(c *C) {
- for i, v := range objectIds {
- t := time.Unix(v.timestamp, 0)
- c.Assert(v.id.Time(), Equals, t, Commentf("#%d Wrong timestamp value", i))
- c.Assert(v.id.Machine(), DeepEquals, v.machine, Commentf("#%d Wrong machine id value", i))
- c.Assert(v.id.Pid(), Equals, v.pid, Commentf("#%d Wrong pid value", i))
- c.Assert(v.id.Counter(), Equals, v.counter, Commentf("#%d Wrong counter value", i))
- }
-}
-
-func (s *S) TestNow(c *C) {
- before := time.Now()
- time.Sleep(1e6)
- now := bson.Now()
- time.Sleep(1e6)
- after := time.Now()
- c.Assert(now.After(before) && now.Before(after), Equals, true, Commentf("now=%s, before=%s, after=%s", now, before, after))
-}
-
-// --------------------------------------------------------------------------
-// ObjectId generation tests.
-
-func (s *S) TestNewObjectId(c *C) {
- // Generate 10 ids
- ids := make([]bson.ObjectId, 10)
- for i := 0; i < 10; i++ {
- ids[i] = bson.NewObjectId()
- }
- for i := 1; i < 10; i++ {
- prevId := ids[i-1]
- id := ids[i]
- // Test for uniqueness among all other 9 generated ids
- for j, tid := range ids {
- if j != i {
- c.Assert(id, Not(Equals), tid, Commentf("Generated ObjectId is not unique"))
- }
- }
- // Check that timestamp was incremented and is within 30 seconds of the previous one
- secs := id.Time().Sub(prevId.Time()).Seconds()
- c.Assert((secs >= 0 && secs <= 30), Equals, true, Commentf("Wrong timestamp in generated ObjectId"))
- // Check that machine ids are the same
- c.Assert(id.Machine(), DeepEquals, prevId.Machine())
- // Check that pids are the same
- c.Assert(id.Pid(), Equals, prevId.Pid())
- // Test for proper increment
- delta := int(id.Counter() - prevId.Counter())
- c.Assert(delta, Equals, 1, Commentf("Wrong increment in generated ObjectId"))
- }
-}
-
-func (s *S) TestNewObjectIdWithTime(c *C) {
- t := time.Unix(12345678, 0)
- id := bson.NewObjectIdWithTime(t)
- c.Assert(id.Time(), Equals, t)
- c.Assert(id.Machine(), DeepEquals, []byte{0x00, 0x00, 0x00})
- c.Assert(int(id.Pid()), Equals, 0)
- c.Assert(int(id.Counter()), Equals, 0)
-}
-
-// --------------------------------------------------------------------------
-// ObjectId JSON marshalling.
-
-type jsonType struct {
- Id bson.ObjectId
-}
-
-var jsonIdTests = []struct {
- value jsonType
- json string
- marshal bool
- unmarshal bool
- error string
-}{{
- value: jsonType{Id: bson.ObjectIdHex("4d88e15b60f486e428412dc9")},
- json: `{"Id":"4d88e15b60f486e428412dc9"}`,
- marshal: true,
- unmarshal: true,
-}, {
- value: jsonType{},
- json: `{"Id":""}`,
- marshal: true,
- unmarshal: true,
-}, {
- value: jsonType{},
- json: `{"Id":null}`,
- marshal: false,
- unmarshal: true,
-}, {
- json: `{"Id":"4d88e15b60f486e428412dc9A"}`,
- error: `invalid ObjectId in JSON: "4d88e15b60f486e428412dc9A"`,
- marshal: false,
- unmarshal: true,
-}, {
- json: `{"Id":"4d88e15b60f486e428412dcZ"}`,
- error: `invalid ObjectId in JSON: "4d88e15b60f486e428412dcZ" .*`,
- marshal: false,
- unmarshal: true,
-}}
-
-func (s *S) TestObjectIdJSONMarshaling(c *C) {
- for _, test := range jsonIdTests {
- if test.marshal {
- data, err := json.Marshal(&test.value)
- if test.error == "" {
- c.Assert(err, IsNil)
- c.Assert(string(data), Equals, test.json)
- } else {
- c.Assert(err, ErrorMatches, test.error)
- }
- }
-
- if test.unmarshal {
- var value jsonType
- err := json.Unmarshal([]byte(test.json), &value)
- if test.error == "" {
- c.Assert(err, IsNil)
- c.Assert(value, DeepEquals, test.value)
- } else {
- c.Assert(err, ErrorMatches, test.error)
- }
- }
- }
-}
-
-// --------------------------------------------------------------------------
-// Spec tests
-
-type specTest struct {
- Description string
- Documents []struct {
- Decoded map[string]interface{}
- Encoded string
- DecodeOnly bool `yaml:"decodeOnly"`
- Error interface{}
- }
-}
-
-func (s *S) TestSpecTests(c *C) {
- for _, data := range specTests {
- var test specTest
- err := yaml.Unmarshal([]byte(data), &test)
- c.Assert(err, IsNil)
-
- c.Logf("Running spec test set %q", test.Description)
-
- for _, doc := range test.Documents {
- if doc.Error != nil {
- continue
- }
- c.Logf("Ensuring %q decodes as %v", doc.Encoded, doc.Decoded)
- var decoded map[string]interface{}
- encoded, err := hex.DecodeString(doc.Encoded)
- c.Assert(err, IsNil)
- err = bson.Unmarshal(encoded, &decoded)
- c.Assert(err, IsNil)
- c.Assert(decoded, DeepEquals, doc.Decoded)
- }
-
- for _, doc := range test.Documents {
- if doc.DecodeOnly || doc.Error != nil {
- continue
- }
- c.Logf("Ensuring %v encodes as %q", doc.Decoded, doc.Encoded)
- encoded, err := bson.Marshal(doc.Decoded)
- c.Assert(err, IsNil)
- c.Assert(strings.ToUpper(hex.EncodeToString(encoded)), Equals, doc.Encoded)
- }
-
- for _, doc := range test.Documents {
- if doc.Error == nil {
- continue
- }
- c.Logf("Ensuring %q errors when decoded: %s", doc.Encoded, doc.Error)
- var decoded map[string]interface{}
- encoded, err := hex.DecodeString(doc.Encoded)
- c.Assert(err, IsNil)
- err = bson.Unmarshal(encoded, &decoded)
- c.Assert(err, NotNil)
- c.Logf("Failed with: %v", err)
- }
- }
-}
-
-// --------------------------------------------------------------------------
-// ObjectId Text encoding.TextUnmarshaler.
-
-var textIdTests = []struct {
- value bson.ObjectId
- text string
- marshal bool
- unmarshal bool
- error string
-}{{
- value: bson.ObjectIdHex("4d88e15b60f486e428412dc9"),
- text: "4d88e15b60f486e428412dc9",
- marshal: true,
- unmarshal: true,
-}, {
- text: "",
- marshal: true,
- unmarshal: true,
-}, {
- text: "4d88e15b60f486e428412dc9A",
- marshal: false,
- unmarshal: true,
- error: `invalid ObjectId: 4d88e15b60f486e428412dc9A`,
-}, {
- text: "4d88e15b60f486e428412dcZ",
- marshal: false,
- unmarshal: true,
- error: `invalid ObjectId: 4d88e15b60f486e428412dcZ .*`,
-}}
-
-func (s *S) TestObjectIdTextMarshaling(c *C) {
- for _, test := range textIdTests {
- if test.marshal {
- data, err := test.value.MarshalText()
- if test.error == "" {
- c.Assert(err, IsNil)
- c.Assert(string(data), Equals, test.text)
- } else {
- c.Assert(err, ErrorMatches, test.error)
- }
- }
-
- if test.unmarshal {
- err := test.value.UnmarshalText([]byte(test.text))
- if test.error == "" {
- c.Assert(err, IsNil)
- if test.value != "" {
- value := bson.ObjectIdHex(test.text)
- c.Assert(value, DeepEquals, test.value)
- }
- } else {
- c.Assert(err, ErrorMatches, test.error)
- }
- }
- }
-}
-
-// --------------------------------------------------------------------------
-// ObjectId XML marshalling.
-
-type xmlType struct {
- Id bson.ObjectId
-}
-
-var xmlIdTests = []struct {
- value xmlType
- xml string
- marshal bool
- unmarshal bool
- error string
-}{{
- value: xmlType{Id: bson.ObjectIdHex("4d88e15b60f486e428412dc9")},
- xml: "4d88e15b60f486e428412dc9",
- marshal: true,
- unmarshal: true,
-}, {
- value: xmlType{},
- xml: "",
- marshal: true,
- unmarshal: true,
-}, {
- xml: "4d88e15b60f486e428412dc9A",
- marshal: false,
- unmarshal: true,
- error: `invalid ObjectId: 4d88e15b60f486e428412dc9A`,
-}, {
- xml: "4d88e15b60f486e428412dcZ",
- marshal: false,
- unmarshal: true,
- error: `invalid ObjectId: 4d88e15b60f486e428412dcZ .*`,
-}}
-
-func (s *S) TestObjectIdXMLMarshaling(c *C) {
- for _, test := range xmlIdTests {
- if test.marshal {
- data, err := xml.Marshal(&test.value)
- if test.error == "" {
- c.Assert(err, IsNil)
- c.Assert(string(data), Equals, test.xml)
- } else {
- c.Assert(err, ErrorMatches, test.error)
- }
- }
-
- if test.unmarshal {
- var value xmlType
- err := xml.Unmarshal([]byte(test.xml), &value)
- if test.error == "" {
- c.Assert(err, IsNil)
- c.Assert(value, DeepEquals, test.value)
- } else {
- c.Assert(err, ErrorMatches, test.error)
- }
- }
- }
-}
-
-// --------------------------------------------------------------------------
-// Some simple benchmarks.
-
-type BenchT struct {
- A, B, C, D, E, F string
-}
-
-type BenchRawT struct {
- A string
- B int
- C bson.M
- D []float64
-}
-
-func (s *S) BenchmarkUnmarhsalStruct(c *C) {
- v := BenchT{A: "A", D: "D", E: "E"}
- data, err := bson.Marshal(&v)
- if err != nil {
- panic(err)
- }
- c.ResetTimer()
- for i := 0; i < c.N; i++ {
- err = bson.Unmarshal(data, &v)
- }
- if err != nil {
- panic(err)
- }
-}
-
-func (s *S) BenchmarkUnmarhsalMap(c *C) {
- m := bson.M{"a": "a", "d": "d", "e": "e"}
- data, err := bson.Marshal(&m)
- if err != nil {
- panic(err)
- }
- c.ResetTimer()
- for i := 0; i < c.N; i++ {
- err = bson.Unmarshal(data, &m)
- }
- if err != nil {
- panic(err)
- }
-}
-
-func (s *S) BenchmarkUnmarshalRaw(c *C) {
- var err error
- m := BenchRawT{
- A: "test_string",
- B: 123,
- C: bson.M{
- "subdoc_int": 12312,
- "subdoc_doc": bson.M{"1": 1},
- },
- D: []float64{0.0, 1.3333, -99.9997, 3.1415},
- }
- data, err := bson.Marshal(&m)
- if err != nil {
- panic(err)
- }
- raw := bson.Raw{}
- c.ResetTimer()
- for i := 0; i < c.N; i++ {
- err = bson.Unmarshal(data, &raw)
- }
- if err != nil {
- panic(err)
- }
-}
-
-func (s *S) BenchmarkNewObjectId(c *C) {
- for i := 0; i < c.N; i++ {
- bson.NewObjectId()
- }
-}
diff --git a/vendor/gopkg.in.o/mgo.v2/bson/decimal.go b/vendor/gopkg.in.o/mgo.v2/bson/decimal.go
deleted file mode 100644
index 3d2f70020..000000000
--- a/vendor/gopkg.in.o/mgo.v2/bson/decimal.go
+++ /dev/null
@@ -1,310 +0,0 @@
-// BSON library for Go
-//
-// Copyright (c) 2010-2012 - Gustavo Niemeyer
-//
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package bson
-
-import (
- "fmt"
- "strconv"
- "strings"
-)
-
-// Decimal128 holds decimal128 BSON values.
-type Decimal128 struct {
- h, l uint64
-}
-
-func (d Decimal128) String() string {
- var pos int // positive sign
- var e int // exponent
- var h, l uint64 // significand high/low
-
- if d.h>>63&1 == 0 {
- pos = 1
- }
-
- switch d.h >> 58 & (1<<5 - 1) {
- case 0x1F:
- return "NaN"
- case 0x1E:
- return "-Inf"[pos:]
- }
-
- l = d.l
- if d.h>>61&3 == 3 {
- // Bits: 1*sign 2*ignored 14*exponent 111*significand.
- // Implicit 0b100 prefix in significand.
- e = int(d.h>>47&(1<<14-1)) - 6176
- //h = 4<<47 | d.h&(1<<47-1)
- // Spec says all of these values are out of range.
- h, l = 0, 0
- } else {
- // Bits: 1*sign 14*exponent 113*significand
- e = int(d.h>>49&(1<<14-1)) - 6176
- h = d.h & (1<<49 - 1)
- }
-
- // Would be handled by the logic below, but that's trivial and common.
- if h == 0 && l == 0 && e == 0 {
- return "-0"[pos:]
- }
-
- var repr [48]byte // Loop 5 times over 9 digits plus dot, negative sign, and leading zero.
- var last = len(repr)
- var i = len(repr)
- var dot = len(repr) + e
- var rem uint32
-Loop:
- for d9 := 0; d9 < 5; d9++ {
- h, l, rem = divmod(h, l, 1e9)
- for d1 := 0; d1 < 9; d1++ {
- // Handle "-0.0", "0.00123400", "-1.00E-6", "1.050E+3", etc.
- if i < len(repr) && (dot == i || l == 0 && h == 0 && rem > 0 && rem < 10 && (dot < i-6 || e > 0)) {
- e += len(repr) - i
- i--
- repr[i] = '.'
- last = i - 1
- dot = len(repr) // Unmark.
- }
- c := '0' + byte(rem%10)
- rem /= 10
- i--
- repr[i] = c
- // Handle "0E+3", "1E+3", etc.
- if l == 0 && h == 0 && rem == 0 && i == len(repr)-1 && (dot < i-5 || e > 0) {
- last = i
- break Loop
- }
- if c != '0' {
- last = i
- }
- // Break early. Works without it, but why.
- if dot > i && l == 0 && h == 0 && rem == 0 {
- break Loop
- }
- }
- }
- repr[last-1] = '-'
- last--
-
- if e > 0 {
- return string(repr[last+pos:]) + "E+" + strconv.Itoa(e)
- }
- if e < 0 {
- return string(repr[last+pos:]) + "E" + strconv.Itoa(e)
- }
- return string(repr[last+pos:])
-}
-
-func divmod(h, l uint64, div uint32) (qh, ql uint64, rem uint32) {
- div64 := uint64(div)
- a := h >> 32
- aq := a / div64
- ar := a % div64
- b := ar<<32 + h&(1<<32-1)
- bq := b / div64
- br := b % div64
- c := br<<32 + l>>32
- cq := c / div64
- cr := c % div64
- d := cr<<32 + l&(1<<32-1)
- dq := d / div64
- dr := d % div64
- return (aq<<32 | bq), (cq<<32 | dq), uint32(dr)
-}
-
-var dNaN = Decimal128{0x1F << 58, 0}
-var dPosInf = Decimal128{0x1E << 58, 0}
-var dNegInf = Decimal128{0x3E << 58, 0}
-
-func dErr(s string) (Decimal128, error) {
- return dNaN, fmt.Errorf("cannot parse %q as a decimal128", s)
-}
-
-func ParseDecimal128(s string) (Decimal128, error) {
- orig := s
- if s == "" {
- return dErr(orig)
- }
- neg := s[0] == '-'
- if neg || s[0] == '+' {
- s = s[1:]
- }
-
- if (len(s) == 3 || len(s) == 8) && (s[0] == 'N' || s[0] == 'n' || s[0] == 'I' || s[0] == 'i') {
- if s == "NaN" || s == "nan" || strings.EqualFold(s, "nan") {
- return dNaN, nil
- }
- if s == "Inf" || s == "inf" || strings.EqualFold(s, "inf") || strings.EqualFold(s, "infinity") {
- if neg {
- return dNegInf, nil
- }
- return dPosInf, nil
- }
- return dErr(orig)
- }
-
- var h, l uint64
- var e int
-
- var add, ovr uint32
- var mul uint32 = 1
- var dot = -1
- var digits = 0
- var i = 0
- for i < len(s) {
- c := s[i]
- if mul == 1e9 {
- h, l, ovr = muladd(h, l, mul, add)
- mul, add = 1, 0
- if ovr > 0 || h&((1<<15-1)<<49) > 0 {
- return dErr(orig)
- }
- }
- if c >= '0' && c <= '9' {
- i++
- if c > '0' || digits > 0 {
- digits++
- }
- if digits > 34 {
- if c == '0' {
- // Exact rounding.
- e++
- continue
- }
- return dErr(orig)
- }
- mul *= 10
- add *= 10
- add += uint32(c - '0')
- continue
- }
- if c == '.' {
- i++
- if dot >= 0 || i == 1 && len(s) == 1 {
- return dErr(orig)
- }
- if i == len(s) {
- break
- }
- if s[i] < '0' || s[i] > '9' || e > 0 {
- return dErr(orig)
- }
- dot = i
- continue
- }
- break
- }
- if i == 0 {
- return dErr(orig)
- }
- if mul > 1 {
- h, l, ovr = muladd(h, l, mul, add)
- if ovr > 0 || h&((1<<15-1)<<49) > 0 {
- return dErr(orig)
- }
- }
- if dot >= 0 {
- e += dot - i
- }
- if i+1 < len(s) && (s[i] == 'E' || s[i] == 'e') {
- i++
- eneg := s[i] == '-'
- if eneg || s[i] == '+' {
- i++
- if i == len(s) {
- return dErr(orig)
- }
- }
- n := 0
- for i < len(s) && n < 1e4 {
- c := s[i]
- i++
- if c < '0' || c > '9' {
- return dErr(orig)
- }
- n *= 10
- n += int(c - '0')
- }
- if eneg {
- n = -n
- }
- e += n
- for e < -6176 {
- // Subnormal.
- var div uint32 = 1
- for div < 1e9 && e < -6176 {
- div *= 10
- e++
- }
- var rem uint32
- h, l, rem = divmod(h, l, div)
- if rem > 0 {
- return dErr(orig)
- }
- }
- for e > 6111 {
- // Clamped.
- var mul uint32 = 1
- for mul < 1e9 && e > 6111 {
- mul *= 10
- e--
- }
- h, l, ovr = muladd(h, l, mul, 0)
- if ovr > 0 || h&((1<<15-1)<<49) > 0 {
- return dErr(orig)
- }
- }
- if e < -6176 || e > 6111 {
- return dErr(orig)
- }
- }
-
- if i < len(s) {
- return dErr(orig)
- }
-
- h |= uint64(e+6176) & uint64(1<<14-1) << 49
- if neg {
- h |= 1 << 63
- }
- return Decimal128{h, l}, nil
-}
-
-func muladd(h, l uint64, mul uint32, add uint32) (resh, resl uint64, overflow uint32) {
- mul64 := uint64(mul)
- a := mul64 * (l & (1<<32 - 1))
- b := a>>32 + mul64*(l>>32)
- c := b>>32 + mul64*(h&(1<<32-1))
- d := c>>32 + mul64*(h>>32)
-
- a = a&(1<<32-1) + uint64(add)
- b = b&(1<<32-1) + a>>32
- c = c&(1<<32-1) + b>>32
- d = d&(1<<32-1) + c>>32
-
- return (d<<32 | c&(1<<32-1)), (b<<32 | a&(1<<32-1)), uint32(d >> 32)
-}
diff --git a/vendor/gopkg.in.o/mgo.v2/bson/decimal_test.go b/vendor/gopkg.in.o/mgo.v2/bson/decimal_test.go
deleted file mode 100644
index a29728094..000000000
--- a/vendor/gopkg.in.o/mgo.v2/bson/decimal_test.go
+++ /dev/null
@@ -1,4109 +0,0 @@
-// BSON library for Go
-//
-// Copyright (c) 2010-2012 - Gustavo Niemeyer
-//
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package bson_test
-
-import (
- "encoding/hex"
- "encoding/json"
- "fmt"
- "regexp"
- "strings"
-
- "gopkg.in/mgo.v2/bson"
-
- . "gopkg.in/check.v1"
-)
-
-// --------------------------------------------------------------------------
-// Decimal tests
-
-type decimalTests struct {
- Valid []struct {
- Description string `json:"description"`
- BSON string `json:"bson"`
- CanonicalBSON string `json:"canonical_bson"`
- ExtJSON string `json:"extjson"`
- CanonicalExtJSON string `json:"canonical_extjson"`
- Lossy bool `json:"lossy"`
- } `json:"valid"`
-
- ParseErrors []struct {
- Description string `json:"description"`
- String string `json:"string"`
- } `json:"parseErrors"`
-}
-
-func extJSONRepr(s string) string {
- var value struct {
- D struct {
- Repr string `json:"$numberDecimal"`
- } `json:"d"`
- }
- err := json.Unmarshal([]byte(s), &value)
- if err != nil {
- panic(err)
- }
- return value.D.Repr
-}
-
-func (s *S) TestDecimalTests(c *C) {
- // These also conform to the spec and are used by Go elsewhere.
- // (e.g. math/big won't parse "Infinity").
- goStr := func(s string) string {
- switch s {
- case "Infinity":
- return "Inf"
- case "-Infinity":
- return "-Inf"
- }
- return s
- }
-
- for _, testEntry := range decimalTestsJSON {
- testFile := testEntry.file
-
- var tests decimalTests
- err := json.Unmarshal([]byte(testEntry.json), &tests)
- c.Assert(err, IsNil)
-
- for _, test := range tests.Valid {
- c.Logf("Running %s test: %s", testFile, test.Description)
-
- test.BSON = strings.ToLower(test.BSON)
-
- // Unmarshal value from BSON data.
- bsonData, err := hex.DecodeString(test.BSON)
- var bsonValue struct{ D interface{} }
- err = bson.Unmarshal(bsonData, &bsonValue)
- c.Assert(err, IsNil)
- dec128, ok := bsonValue.D.(bson.Decimal128)
- c.Assert(ok, Equals, true)
-
- // Extract ExtJSON representations (canonical and not).
- extjRepr := extJSONRepr(test.ExtJSON)
- cextjRepr := extjRepr
- if test.CanonicalExtJSON != "" {
- cextjRepr = extJSONRepr(test.CanonicalExtJSON)
- }
-
- wantRepr := goStr(cextjRepr)
-
- // Generate canonical representation.
- c.Assert(dec128.String(), Equals, wantRepr)
-
- // Parse original canonical representation.
- parsed, err := bson.ParseDecimal128(cextjRepr)
- c.Assert(err, IsNil)
- c.Assert(parsed.String(), Equals, wantRepr)
-
- // Parse non-canonical representation.
- parsed, err = bson.ParseDecimal128(extjRepr)
- c.Assert(err, IsNil)
- c.Assert(parsed.String(), Equals, wantRepr)
-
- // Parse Go canonical representation (Inf vs. Infinity).
- parsed, err = bson.ParseDecimal128(wantRepr)
- c.Assert(err, IsNil)
- c.Assert(parsed.String(), Equals, wantRepr)
-
- // Marshal original value back into BSON data.
- data, err := bson.Marshal(bsonValue)
- c.Assert(err, IsNil)
- c.Assert(hex.EncodeToString(data), Equals, test.BSON)
-
- if test.Lossy {
- continue
- }
-
- // Marshal the parsed canonical representation.
- var parsedValue struct{ D interface{} }
- parsedValue.D = parsed
- data, err = bson.Marshal(parsedValue)
- c.Assert(err, IsNil)
- c.Assert(hex.EncodeToString(data), Equals, test.BSON)
- }
-
- for _, test := range tests.ParseErrors {
- c.Logf("Running %s parse error test: %s (string %q)", testFile, test.Description, test.String)
-
- _, err := bson.ParseDecimal128(test.String)
- quoted := regexp.QuoteMeta(fmt.Sprintf("%q", test.String))
- c.Assert(err, ErrorMatches, `cannot parse `+quoted+` as a decimal128`)
- }
- }
-}
-
-const decBenchNum = "9.999999999999999999999999999999999E+6144"
-
-func (s *S) BenchmarkDecimal128String(c *C) {
- d, err := bson.ParseDecimal128(decBenchNum)
- c.Assert(err, IsNil)
- c.Assert(d.String(), Equals, decBenchNum)
-
- c.ResetTimer()
- for i := 0; i < c.N; i++ {
- d.String()
- }
-}
-
-func (s *S) BenchmarkDecimal128Parse(c *C) {
- var err error
- c.ResetTimer()
- for i := 0; i < c.N; i++ {
- _, err = bson.ParseDecimal128(decBenchNum)
- }
- if err != nil {
- panic(err)
- }
-}
-
-var decimalTestsJSON = []struct{ file, json string }{
- {"decimal128-1.json", `
-{
- "description": "Decimal128",
- "bson_type": "0x13",
- "test_key": "d",
- "valid": [
- {
- "description": "Special - Canonical NaN",
- "bson": "180000001364000000000000000000000000000000007C00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"NaN\"}}"
- },
- {
- "description": "Special - Negative NaN",
- "bson": "18000000136400000000000000000000000000000000FC00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"NaN\"}}",
- "lossy": true
- },
- {
- "description": "Special - Negative NaN",
- "bson": "18000000136400000000000000000000000000000000FC00",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"NaN\"}}",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-NaN\"}}",
- "lossy": true
- },
- {
- "description": "Special - Canonical SNaN",
- "bson": "180000001364000000000000000000000000000000007E00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"NaN\"}}",
- "lossy": true
- },
- {
- "description": "Special - Negative SNaN",
- "bson": "18000000136400000000000000000000000000000000FE00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"NaN\"}}",
- "lossy": true
- },
- {
- "description": "Special - NaN with a payload",
- "bson": "180000001364001200000000000000000000000000007E00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"NaN\"}}",
- "lossy": true
- },
- {
- "description": "Special - Canonical Positive Infinity",
- "bson": "180000001364000000000000000000000000000000007800",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"Infinity\"}}"
- },
- {
- "description": "Special - Canonical Negative Infinity",
- "bson": "18000000136400000000000000000000000000000000F800",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-Infinity\"}}"
- },
- {
- "description": "Special - Invalid representation treated as 0",
- "bson": "180000001364000000000000000000000000000000106C00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0\"}}",
- "lossy": true
- },
- {
- "description": "Special - Invalid representation treated as -0",
- "bson": "18000000136400DCBA9876543210DEADBEEF00000010EC00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0\"}}",
- "lossy": true
- },
- {
- "description": "Special - Invalid representation treated as 0E3",
- "bson": "18000000136400FFFFFFFFFFFFFFFFFFFFFFFFFFFF116C00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+3\"}}",
- "lossy": true
- },
- {
- "description": "Regular - Adjusted Exponent Limit",
- "bson": "18000000136400F2AF967ED05C82DE3297FF6FDE3CF22F00",
- "extjson": "{\"d\": { \"$numberDecimal\": \"0.000001234567890123456789012345678901234\" }}"
- },
- {
- "description": "Regular - Smallest",
- "bson": "18000000136400D204000000000000000000000000343000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.001234\"}}"
- },
- {
- "description": "Regular - Smallest with Trailing Zeros",
- "bson": "1800000013640040EF5A07000000000000000000002A3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00123400000\"}}"
- },
- {
- "description": "Regular - 0.1",
- "bson": "1800000013640001000000000000000000000000003E3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1\"}}"
- },
- {
- "description": "Regular - 0.1234567890123456789012345678901234",
- "bson": "18000000136400F2AF967ED05C82DE3297FF6FDE3CFC2F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1234567890123456789012345678901234\"}}"
- },
- {
- "description": "Regular - 0",
- "bson": "180000001364000000000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0\"}}"
- },
- {
- "description": "Regular - -0",
- "bson": "18000000136400000000000000000000000000000040B000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0\"}}"
- },
- {
- "description": "Regular - -0.0",
- "bson": "1800000013640000000000000000000000000000003EB000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.0\"}}"
- },
- {
- "description": "Regular - 2",
- "bson": "180000001364000200000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"2\"}}"
- },
- {
- "description": "Regular - 2.000",
- "bson": "18000000136400D0070000000000000000000000003A3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"2.000\"}}"
- },
- {
- "description": "Regular - Largest",
- "bson": "18000000136400F2AF967ED05C82DE3297FF6FDE3C403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1234567890123456789012345678901234\"}}"
- },
- {
- "description": "Scientific - Tiniest",
- "bson": "18000000136400FFFFFFFF638E8D37C087ADBE09ED010000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"9.999999999999999999999999999999999E-6143\"}}"
- },
- {
- "description": "Scientific - Tiny",
- "bson": "180000001364000100000000000000000000000000000000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E-6176\"}}"
- },
- {
- "description": "Scientific - Negative Tiny",
- "bson": "180000001364000100000000000000000000000000008000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-1E-6176\"}}"
- },
- {
- "description": "Scientific - Adjusted Exponent Limit",
- "bson": "18000000136400F2AF967ED05C82DE3297FF6FDE3CF02F00",
- "extjson": "{\"d\": { \"$numberDecimal\": \"1.234567890123456789012345678901234E-7\" }}"
- },
- {
- "description": "Scientific - Fractional",
- "bson": "1800000013640064000000000000000000000000002CB000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-1.00E-8\"}}"
- },
- {
- "description": "Scientific - 0 with Exponent",
- "bson": "180000001364000000000000000000000000000000205F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+6000\"}}"
- },
- {
- "description": "Scientific - 0 with Negative Exponent",
- "bson": "1800000013640000000000000000000000000000007A2B00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-611\"}}"
- },
- {
- "description": "Scientific - No Decimal with Signed Exponent",
- "bson": "180000001364000100000000000000000000000000463000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+3\"}}"
- },
- {
- "description": "Scientific - Trailing Zero",
- "bson": "180000001364001A04000000000000000000000000423000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.050E+4\"}}"
- },
- {
- "description": "Scientific - With Decimal",
- "bson": "180000001364006900000000000000000000000000423000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.05E+3\"}}"
- },
- {
- "description": "Scientific - Full",
- "bson": "18000000136400FFFFFFFFFFFFFFFFFFFFFFFFFFFF403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"5192296858534827628530496329220095\"}}"
- },
- {
- "description": "Scientific - Large",
- "bson": "18000000136400000000000A5BC138938D44C64D31FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000000000000000000000000E+6144\"}}"
- },
- {
- "description": "Scientific - Largest",
- "bson": "18000000136400FFFFFFFF638E8D37C087ADBE09EDFF5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"9.999999999999999999999999999999999E+6144\"}}"
- },
- {
- "description": "Non-Canonical Parsing - Exponent Normalization",
- "bson": "1800000013640064000000000000000000000000002CB000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-100E-10\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-1.00E-8\"}}"
- },
- {
- "description": "Non-Canonical Parsing - Unsigned Positive Exponent",
- "bson": "180000001364000100000000000000000000000000463000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E3\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+3\"}}"
- },
- {
- "description": "Non-Canonical Parsing - Lowercase Exponent Identifier",
- "bson": "180000001364000100000000000000000000000000463000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1e+3\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+3\"}}"
- },
- {
- "description": "Non-Canonical Parsing - Long Significand with Exponent",
- "bson": "1800000013640079D9E0F9763ADA429D0200000000583000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"12345689012345789012345E+12\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.2345689012345789012345E+34\"}}"
- },
- {
- "description": "Non-Canonical Parsing - Positive Sign",
- "bson": "18000000136400F2AF967ED05C82DE3297FF6FDE3C403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"+1234567890123456789012345678901234\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1234567890123456789012345678901234\"}}"
- },
- {
- "description": "Non-Canonical Parsing - Long Decimal String",
- "bson": "180000001364000100000000000000000000000000722800",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \".000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E-999\"}}"
- },
- {
- "description": "Non-Canonical Parsing - nan",
- "bson": "180000001364000000000000000000000000000000007C00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"nan\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"NaN\"}}"
- },
- {
- "description": "Non-Canonical Parsing - nAn",
- "bson": "180000001364000000000000000000000000000000007C00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"nAn\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"NaN\"}}"
- },
- {
- "description": "Non-Canonical Parsing - +infinity",
- "bson": "180000001364000000000000000000000000000000007800",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"+infinity\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"Infinity\"}}"
- },
- {
- "description": "Non-Canonical Parsing - infinity",
- "bson": "180000001364000000000000000000000000000000007800",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"infinity\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"Infinity\"}}"
- },
- {
- "description": "Non-Canonical Parsing - infiniTY",
- "bson": "180000001364000000000000000000000000000000007800",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"infiniTY\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"Infinity\"}}"
- },
- {
- "description": "Non-Canonical Parsing - inf",
- "bson": "180000001364000000000000000000000000000000007800",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"inf\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"Infinity\"}}"
- },
- {
- "description": "Non-Canonical Parsing - inF",
- "bson": "180000001364000000000000000000000000000000007800",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"inF\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"Infinity\"}}"
- },
- {
- "description": "Non-Canonical Parsing - -infinity",
- "bson": "18000000136400000000000000000000000000000000F800",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-infinity\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-Infinity\"}}"
- },
- {
- "description": "Non-Canonical Parsing - -infiniTy",
- "bson": "18000000136400000000000000000000000000000000F800",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-infiniTy\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-Infinity\"}}"
- },
- {
- "description": "Non-Canonical Parsing - -Inf",
- "bson": "18000000136400000000000000000000000000000000F800",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-Infinity\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-Infinity\"}}"
- },
- {
- "description": "Non-Canonical Parsing - -inf",
- "bson": "18000000136400000000000000000000000000000000F800",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-inf\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-Infinity\"}}"
- },
- {
- "description": "Non-Canonical Parsing - -inF",
- "bson": "18000000136400000000000000000000000000000000F800",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-inF\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-Infinity\"}}"
- },
- {
- "description": "Rounded Subnormal number",
- "bson": "180000001364000100000000000000000000000000000000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"10E-6177\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E-6176\"}}"
- },
- {
- "description": "Clamped",
- "bson": "180000001364000a00000000000000000000000000fe5f00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E6112\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E+6112\"}}"
- },
- {
- "description": "Exact rounding",
- "bson": "18000000136400000000000a5bc138938d44c64d31cc3700",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000000000000000000000000E+999\"}}"
- }
- ]
-}
-`},
-
- {"decimal128-2.json", `
-{
- "description": "Decimal128",
- "bson_type": "0x13",
- "test_key": "d",
- "valid": [
- {
- "description": "[decq021] Normality",
- "bson": "18000000136400F2AF967ED05C82DE3297FF6FDE3C40B000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-1234567890123456789012345678901234\"}}"
- },
- {
- "description": "[decq823] values around [u]int32 edges (zeros done earlier)",
- "bson": "18000000136400010000800000000000000000000040B000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-2147483649\"}}"
- },
- {
- "description": "[decq822] values around [u]int32 edges (zeros done earlier)",
- "bson": "18000000136400000000800000000000000000000040B000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-2147483648\"}}"
- },
- {
- "description": "[decq821] values around [u]int32 edges (zeros done earlier)",
- "bson": "18000000136400FFFFFF7F0000000000000000000040B000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-2147483647\"}}"
- },
- {
- "description": "[decq820] values around [u]int32 edges (zeros done earlier)",
- "bson": "18000000136400FEFFFF7F0000000000000000000040B000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-2147483646\"}}"
- },
- {
- "description": "[decq152] fold-downs (more below)",
- "bson": "18000000136400393000000000000000000000000040B000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-12345\"}}"
- },
- {
- "description": "[decq154] fold-downs (more below)",
- "bson": "18000000136400D20400000000000000000000000040B000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-1234\"}}"
- },
- {
- "description": "[decq006] derivative canonical plain strings",
- "bson": "18000000136400EE0200000000000000000000000040B000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-750\"}}"
- },
- {
- "description": "[decq164] fold-downs (more below)",
- "bson": "1800000013640039300000000000000000000000003CB000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-123.45\"}}"
- },
- {
- "description": "[decq156] fold-downs (more below)",
- "bson": "180000001364007B0000000000000000000000000040B000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-123\"}}"
- },
- {
- "description": "[decq008] derivative canonical plain strings",
- "bson": "18000000136400EE020000000000000000000000003EB000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-75.0\"}}"
- },
- {
- "description": "[decq158] fold-downs (more below)",
- "bson": "180000001364000C0000000000000000000000000040B000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-12\"}}"
- },
- {
- "description": "[decq122] Nmax and similar",
- "bson": "18000000136400FFFFFFFF638E8D37C087ADBE09EDFFDF00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-9.999999999999999999999999999999999E+6144\"}}"
- },
- {
- "description": "[decq002] (mostly derived from the Strawman 4 document and examples)",
- "bson": "18000000136400EE020000000000000000000000003CB000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-7.50\"}}"
- },
- {
- "description": "[decq004] derivative canonical plain strings",
- "bson": "18000000136400EE0200000000000000000000000042B000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-7.50E+3\"}}"
- },
- {
- "description": "[decq018] derivative canonical plain strings",
- "bson": "18000000136400EE020000000000000000000000002EB000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-7.50E-7\"}}"
- },
- {
- "description": "[decq125] Nmax and similar",
- "bson": "18000000136400F2AF967ED05C82DE3297FF6FDE3CFEDF00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-1.234567890123456789012345678901234E+6144\"}}"
- },
- {
- "description": "[decq131] fold-downs (more below)",
- "bson": "18000000136400000000807F1BCF85B27059C8A43CFEDF00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-1.230000000000000000000000000000000E+6144\"}}"
- },
- {
- "description": "[decq162] fold-downs (more below)",
- "bson": "180000001364007B000000000000000000000000003CB000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-1.23\"}}"
- },
- {
- "description": "[decq176] Nmin and below",
- "bson": "18000000136400010000000A5BC138938D44C64D31008000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-1.000000000000000000000000000000001E-6143\"}}"
- },
- {
- "description": "[decq174] Nmin and below",
- "bson": "18000000136400000000000A5BC138938D44C64D31008000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-1.000000000000000000000000000000000E-6143\"}}"
- },
- {
- "description": "[decq133] fold-downs (more below)",
- "bson": "18000000136400000000000A5BC138938D44C64D31FEDF00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-1.000000000000000000000000000000000E+6144\"}}"
- },
- {
- "description": "[decq160] fold-downs (more below)",
- "bson": "18000000136400010000000000000000000000000040B000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-1\"}}"
- },
- {
- "description": "[decq172] Nmin and below",
- "bson": "180000001364000100000000000000000000000000428000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-1E-6143\"}}"
- },
- {
- "description": "[decq010] derivative canonical plain strings",
- "bson": "18000000136400EE020000000000000000000000003AB000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.750\"}}"
- },
- {
- "description": "[decq012] derivative canonical plain strings",
- "bson": "18000000136400EE0200000000000000000000000038B000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.0750\"}}"
- },
- {
- "description": "[decq014] derivative canonical plain strings",
- "bson": "18000000136400EE0200000000000000000000000034B000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.000750\"}}"
- },
- {
- "description": "[decq016] derivative canonical plain strings",
- "bson": "18000000136400EE0200000000000000000000000030B000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.00000750\"}}"
- },
- {
- "description": "[decq404] zeros",
- "bson": "180000001364000000000000000000000000000000000000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-6176\"}}"
- },
- {
- "description": "[decq424] negative zeros",
- "bson": "180000001364000000000000000000000000000000008000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E-6176\"}}"
- },
- {
- "description": "[decq407] zeros",
- "bson": "1800000013640000000000000000000000000000003C3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00\"}}"
- },
- {
- "description": "[decq427] negative zeros",
- "bson": "1800000013640000000000000000000000000000003CB000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.00\"}}"
- },
- {
- "description": "[decq409] zeros",
- "bson": "180000001364000000000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0\"}}"
- },
- {
- "description": "[decq428] negative zeros",
- "bson": "18000000136400000000000000000000000000000040B000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0\"}}"
- },
- {
- "description": "[decq700] Selected DPD codes",
- "bson": "180000001364000000000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0\"}}"
- },
- {
- "description": "[decq406] zeros",
- "bson": "1800000013640000000000000000000000000000003C3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00\"}}"
- },
- {
- "description": "[decq426] negative zeros",
- "bson": "1800000013640000000000000000000000000000003CB000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.00\"}}"
- },
- {
- "description": "[decq410] zeros",
- "bson": "180000001364000000000000000000000000000000463000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+3\"}}"
- },
- {
- "description": "[decq431] negative zeros",
- "bson": "18000000136400000000000000000000000000000046B000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E+3\"}}"
- },
- {
- "description": "[decq419] clamped zeros...",
- "bson": "180000001364000000000000000000000000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+6111\"}}"
- },
- {
- "description": "[decq432] negative zeros",
- "bson": "180000001364000000000000000000000000000000FEDF00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E+6111\"}}"
- },
- {
- "description": "[decq405] zeros",
- "bson": "180000001364000000000000000000000000000000000000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-6176\"}}"
- },
- {
- "description": "[decq425] negative zeros",
- "bson": "180000001364000000000000000000000000000000008000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E-6176\"}}"
- },
- {
- "description": "[decq508] Specials",
- "bson": "180000001364000000000000000000000000000000007800",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"Infinity\"}}"
- },
- {
- "description": "[decq528] Specials",
- "bson": "18000000136400000000000000000000000000000000F800",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-Infinity\"}}"
- },
- {
- "description": "[decq541] Specials",
- "bson": "180000001364000000000000000000000000000000007C00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"NaN\"}}"
- },
- {
- "description": "[decq074] Nmin and below",
- "bson": "18000000136400000000000A5BC138938D44C64D31000000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000000000000000000000000E-6143\"}}"
- },
- {
- "description": "[decq602] fold-down full sequence",
- "bson": "18000000136400000000000A5BC138938D44C64D31FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000000000000000000000000E+6144\"}}"
- },
- {
- "description": "[decq604] fold-down full sequence",
- "bson": "180000001364000000000081EFAC855B416D2DEE04FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000000000000000000000000000000E+6143\"}}"
- },
- {
- "description": "[decq606] fold-down full sequence",
- "bson": "1800000013640000000080264B91C02220BE377E00FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0000000000000000000000000000000E+6142\"}}"
- },
- {
- "description": "[decq608] fold-down full sequence",
- "bson": "1800000013640000000040EAED7446D09C2C9F0C00FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000000000000000000000E+6141\"}}"
- },
- {
- "description": "[decq610] fold-down full sequence",
- "bson": "18000000136400000000A0CA17726DAE0F1E430100FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000000000000000000000000000E+6140\"}}"
- },
- {
- "description": "[decq612] fold-down full sequence",
- "bson": "18000000136400000000106102253E5ECE4F200000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0000000000000000000000000000E+6139\"}}"
- },
- {
- "description": "[decq614] fold-down full sequence",
- "bson": "18000000136400000000E83C80D09F3C2E3B030000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000000000000000000E+6138\"}}"
- },
- {
- "description": "[decq616] fold-down full sequence",
- "bson": "18000000136400000000E4D20CC8DCD2B752000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000000000000000000000000E+6137\"}}"
- },
- {
- "description": "[decq618] fold-down full sequence",
- "bson": "180000001364000000004A48011416954508000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0000000000000000000000000E+6136\"}}"
- },
- {
- "description": "[decq620] fold-down full sequence",
- "bson": "18000000136400000000A1EDCCCE1BC2D300000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000000000000000E+6135\"}}"
- },
- {
- "description": "[decq622] fold-down full sequence",
- "bson": "18000000136400000080F64AE1C7022D1500000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000000000000000000000E+6134\"}}"
- },
- {
- "description": "[decq624] fold-down full sequence",
- "bson": "18000000136400000040B2BAC9E0191E0200000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0000000000000000000000E+6133\"}}"
- },
- {
- "description": "[decq626] fold-down full sequence",
- "bson": "180000001364000000A0DEC5ADC935360000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000000000000E+6132\"}}"
- },
- {
- "description": "[decq628] fold-down full sequence",
- "bson": "18000000136400000010632D5EC76B050000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000000000000000000E+6131\"}}"
- },
- {
- "description": "[decq630] fold-down full sequence",
- "bson": "180000001364000000E8890423C78A000000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0000000000000000000E+6130\"}}"
- },
- {
- "description": "[decq632] fold-down full sequence",
- "bson": "18000000136400000064A7B3B6E00D000000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000000000E+6129\"}}"
- },
- {
- "description": "[decq634] fold-down full sequence",
- "bson": "1800000013640000008A5D78456301000000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000000000000000E+6128\"}}"
- },
- {
- "description": "[decq636] fold-down full sequence",
- "bson": "180000001364000000C16FF2862300000000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0000000000000000E+6127\"}}"
- },
- {
- "description": "[decq638] fold-down full sequence",
- "bson": "180000001364000080C6A47E8D0300000000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000000E+6126\"}}"
- },
- {
- "description": "[decq640] fold-down full sequence",
- "bson": "1800000013640000407A10F35A0000000000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000000000000E+6125\"}}"
- },
- {
- "description": "[decq642] fold-down full sequence",
- "bson": "1800000013640000A0724E18090000000000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0000000000000E+6124\"}}"
- },
- {
- "description": "[decq644] fold-down full sequence",
- "bson": "180000001364000010A5D4E8000000000000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000E+6123\"}}"
- },
- {
- "description": "[decq646] fold-down full sequence",
- "bson": "1800000013640000E8764817000000000000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000000000E+6122\"}}"
- },
- {
- "description": "[decq648] fold-down full sequence",
- "bson": "1800000013640000E40B5402000000000000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0000000000E+6121\"}}"
- },
- {
- "description": "[decq650] fold-down full sequence",
- "bson": "1800000013640000CA9A3B00000000000000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000E+6120\"}}"
- },
- {
- "description": "[decq652] fold-down full sequence",
- "bson": "1800000013640000E1F50500000000000000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000000E+6119\"}}"
- },
- {
- "description": "[decq654] fold-down full sequence",
- "bson": "180000001364008096980000000000000000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0000000E+6118\"}}"
- },
- {
- "description": "[decq656] fold-down full sequence",
- "bson": "1800000013640040420F0000000000000000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000E+6117\"}}"
- },
- {
- "description": "[decq658] fold-down full sequence",
- "bson": "18000000136400A086010000000000000000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000E+6116\"}}"
- },
- {
- "description": "[decq660] fold-down full sequence",
- "bson": "180000001364001027000000000000000000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0000E+6115\"}}"
- },
- {
- "description": "[decq662] fold-down full sequence",
- "bson": "18000000136400E803000000000000000000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000E+6114\"}}"
- },
- {
- "description": "[decq664] fold-down full sequence",
- "bson": "180000001364006400000000000000000000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00E+6113\"}}"
- },
- {
- "description": "[decq666] fold-down full sequence",
- "bson": "180000001364000A00000000000000000000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E+6112\"}}"
- },
- {
- "description": "[decq060] fold-downs (more below)",
- "bson": "180000001364000100000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1\"}}"
- },
- {
- "description": "[decq670] fold-down full sequence",
- "bson": "180000001364000100000000000000000000000000FC5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6110\"}}"
- },
- {
- "description": "[decq668] fold-down full sequence",
- "bson": "180000001364000100000000000000000000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6111\"}}"
- },
- {
- "description": "[decq072] Nmin and below",
- "bson": "180000001364000100000000000000000000000000420000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E-6143\"}}"
- },
- {
- "description": "[decq076] Nmin and below",
- "bson": "18000000136400010000000A5BC138938D44C64D31000000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000000000000000000000001E-6143\"}}"
- },
- {
- "description": "[decq036] fold-downs (more below)",
- "bson": "18000000136400000000807F1BCF85B27059C8A43CFE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.230000000000000000000000000000000E+6144\"}}"
- },
- {
- "description": "[decq062] fold-downs (more below)",
- "bson": "180000001364007B000000000000000000000000003C3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.23\"}}"
- },
- {
- "description": "[decq034] Nmax and similar",
- "bson": "18000000136400F2AF967ED05C82DE3297FF6FDE3CFE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.234567890123456789012345678901234E+6144\"}}"
- },
- {
- "description": "[decq441] exponent lengths",
- "bson": "180000001364000700000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"7\"}}"
- },
- {
- "description": "[decq449] exponent lengths",
- "bson": "1800000013640007000000000000000000000000001E5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"7E+5999\"}}"
- },
- {
- "description": "[decq447] exponent lengths",
- "bson": "1800000013640007000000000000000000000000000E3800",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"7E+999\"}}"
- },
- {
- "description": "[decq445] exponent lengths",
- "bson": "180000001364000700000000000000000000000000063100",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"7E+99\"}}"
- },
- {
- "description": "[decq443] exponent lengths",
- "bson": "180000001364000700000000000000000000000000523000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"7E+9\"}}"
- },
- {
- "description": "[decq842] VG testcase",
- "bson": "180000001364000000FED83F4E7C9FE4E269E38A5BCD1700",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"7.049000000000010795488000000000000E-3097\"}}"
- },
- {
- "description": "[decq841] VG testcase",
- "bson": "180000001364000000203B9DB5056F000000000000002400",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"8.000000000000000000E-1550\"}}"
- },
- {
- "description": "[decq840] VG testcase",
- "bson": "180000001364003C17258419D710C42F0000000000002400",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"8.81125000000001349436E-1548\"}}"
- },
- {
- "description": "[decq701] Selected DPD codes",
- "bson": "180000001364000900000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"9\"}}"
- },
- {
- "description": "[decq032] Nmax and similar",
- "bson": "18000000136400FFFFFFFF638E8D37C087ADBE09EDFF5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"9.999999999999999999999999999999999E+6144\"}}"
- },
- {
- "description": "[decq702] Selected DPD codes",
- "bson": "180000001364000A00000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"10\"}}"
- },
- {
- "description": "[decq057] fold-downs (more below)",
- "bson": "180000001364000C00000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"12\"}}"
- },
- {
- "description": "[decq703] Selected DPD codes",
- "bson": "180000001364001300000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"19\"}}"
- },
- {
- "description": "[decq704] Selected DPD codes",
- "bson": "180000001364001400000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"20\"}}"
- },
- {
- "description": "[decq705] Selected DPD codes",
- "bson": "180000001364001D00000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"29\"}}"
- },
- {
- "description": "[decq706] Selected DPD codes",
- "bson": "180000001364001E00000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"30\"}}"
- },
- {
- "description": "[decq707] Selected DPD codes",
- "bson": "180000001364002700000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"39\"}}"
- },
- {
- "description": "[decq708] Selected DPD codes",
- "bson": "180000001364002800000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"40\"}}"
- },
- {
- "description": "[decq709] Selected DPD codes",
- "bson": "180000001364003100000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"49\"}}"
- },
- {
- "description": "[decq710] Selected DPD codes",
- "bson": "180000001364003200000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"50\"}}"
- },
- {
- "description": "[decq711] Selected DPD codes",
- "bson": "180000001364003B00000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"59\"}}"
- },
- {
- "description": "[decq712] Selected DPD codes",
- "bson": "180000001364003C00000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"60\"}}"
- },
- {
- "description": "[decq713] Selected DPD codes",
- "bson": "180000001364004500000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"69\"}}"
- },
- {
- "description": "[decq714] Selected DPD codes",
- "bson": "180000001364004600000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"70\"}}"
- },
- {
- "description": "[decq715] Selected DPD codes",
- "bson": "180000001364004700000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"71\"}}"
- },
- {
- "description": "[decq716] Selected DPD codes",
- "bson": "180000001364004800000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"72\"}}"
- },
- {
- "description": "[decq717] Selected DPD codes",
- "bson": "180000001364004900000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"73\"}}"
- },
- {
- "description": "[decq718] Selected DPD codes",
- "bson": "180000001364004A00000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"74\"}}"
- },
- {
- "description": "[decq719] Selected DPD codes",
- "bson": "180000001364004B00000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"75\"}}"
- },
- {
- "description": "[decq720] Selected DPD codes",
- "bson": "180000001364004C00000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"76\"}}"
- },
- {
- "description": "[decq721] Selected DPD codes",
- "bson": "180000001364004D00000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"77\"}}"
- },
- {
- "description": "[decq722] Selected DPD codes",
- "bson": "180000001364004E00000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"78\"}}"
- },
- {
- "description": "[decq723] Selected DPD codes",
- "bson": "180000001364004F00000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"79\"}}"
- },
- {
- "description": "[decq056] fold-downs (more below)",
- "bson": "180000001364007B00000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"123\"}}"
- },
- {
- "description": "[decq064] fold-downs (more below)",
- "bson": "1800000013640039300000000000000000000000003C3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"123.45\"}}"
- },
- {
- "description": "[decq732] Selected DPD codes",
- "bson": "180000001364000802000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"520\"}}"
- },
- {
- "description": "[decq733] Selected DPD codes",
- "bson": "180000001364000902000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"521\"}}"
- },
- {
- "description": "[decq740] DPD: one of each of the huffman groups",
- "bson": "180000001364000903000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"777\"}}"
- },
- {
- "description": "[decq741] DPD: one of each of the huffman groups",
- "bson": "180000001364000A03000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"778\"}}"
- },
- {
- "description": "[decq742] DPD: one of each of the huffman groups",
- "bson": "180000001364001303000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"787\"}}"
- },
- {
- "description": "[decq746] DPD: one of each of the huffman groups",
- "bson": "180000001364001F03000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"799\"}}"
- },
- {
- "description": "[decq743] DPD: one of each of the huffman groups",
- "bson": "180000001364006D03000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"877\"}}"
- },
- {
- "description": "[decq753] DPD all-highs cases (includes the 24 redundant codes)",
- "bson": "180000001364007803000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"888\"}}"
- },
- {
- "description": "[decq754] DPD all-highs cases (includes the 24 redundant codes)",
- "bson": "180000001364007903000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"889\"}}"
- },
- {
- "description": "[decq760] DPD all-highs cases (includes the 24 redundant codes)",
- "bson": "180000001364008203000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"898\"}}"
- },
- {
- "description": "[decq764] DPD all-highs cases (includes the 24 redundant codes)",
- "bson": "180000001364008303000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"899\"}}"
- },
- {
- "description": "[decq745] DPD: one of each of the huffman groups",
- "bson": "18000000136400D303000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"979\"}}"
- },
- {
- "description": "[decq770] DPD all-highs cases (includes the 24 redundant codes)",
- "bson": "18000000136400DC03000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"988\"}}"
- },
- {
- "description": "[decq774] DPD all-highs cases (includes the 24 redundant codes)",
- "bson": "18000000136400DD03000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"989\"}}"
- },
- {
- "description": "[decq730] Selected DPD codes",
- "bson": "18000000136400E203000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"994\"}}"
- },
- {
- "description": "[decq731] Selected DPD codes",
- "bson": "18000000136400E303000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"995\"}}"
- },
- {
- "description": "[decq744] DPD: one of each of the huffman groups",
- "bson": "18000000136400E503000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"997\"}}"
- },
- {
- "description": "[decq780] DPD all-highs cases (includes the 24 redundant codes)",
- "bson": "18000000136400E603000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"998\"}}"
- },
- {
- "description": "[decq787] DPD all-highs cases (includes the 24 redundant codes)",
- "bson": "18000000136400E703000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"999\"}}"
- },
- {
- "description": "[decq053] fold-downs (more below)",
- "bson": "18000000136400D204000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1234\"}}"
- },
- {
- "description": "[decq052] fold-downs (more below)",
- "bson": "180000001364003930000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"12345\"}}"
- },
- {
- "description": "[decq792] Miscellaneous (testers' queries, etc.)",
- "bson": "180000001364003075000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"30000\"}}"
- },
- {
- "description": "[decq793] Miscellaneous (testers' queries, etc.)",
- "bson": "1800000013640090940D0000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"890000\"}}"
- },
- {
- "description": "[decq824] values around [u]int32 edges (zeros done earlier)",
- "bson": "18000000136400FEFFFF7F00000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"2147483646\"}}"
- },
- {
- "description": "[decq825] values around [u]int32 edges (zeros done earlier)",
- "bson": "18000000136400FFFFFF7F00000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"2147483647\"}}"
- },
- {
- "description": "[decq826] values around [u]int32 edges (zeros done earlier)",
- "bson": "180000001364000000008000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"2147483648\"}}"
- },
- {
- "description": "[decq827] values around [u]int32 edges (zeros done earlier)",
- "bson": "180000001364000100008000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"2147483649\"}}"
- },
- {
- "description": "[decq828] values around [u]int32 edges (zeros done earlier)",
- "bson": "18000000136400FEFFFFFF00000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"4294967294\"}}"
- },
- {
- "description": "[decq829] values around [u]int32 edges (zeros done earlier)",
- "bson": "18000000136400FFFFFFFF00000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"4294967295\"}}"
- },
- {
- "description": "[decq830] values around [u]int32 edges (zeros done earlier)",
- "bson": "180000001364000000000001000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"4294967296\"}}"
- },
- {
- "description": "[decq831] values around [u]int32 edges (zeros done earlier)",
- "bson": "180000001364000100000001000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"4294967297\"}}"
- },
- {
- "description": "[decq022] Normality",
- "bson": "18000000136400C7711CC7B548F377DC80A131C836403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1111111111111111111111111111111111\"}}"
- },
- {
- "description": "[decq020] Normality",
- "bson": "18000000136400F2AF967ED05C82DE3297FF6FDE3C403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1234567890123456789012345678901234\"}}"
- },
- {
- "description": "[decq550] Specials",
- "bson": "18000000136400FFFFFFFF638E8D37C087ADBE09ED413000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"9999999999999999999999999999999999\"}}"
- }
- ]
-}
-`},
-
- {"decimal128-3.json", `
-{
- "description": "Decimal128",
- "bson_type": "0x13",
- "test_key": "d",
- "valid": [
- {
- "description": "[basx066] strings without E cannot generate E in result",
- "bson": "18000000136400185C0ACE0000000000000000000038B000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-00345678.5432\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-345678.5432\"}}"
- },
- {
- "description": "[basx065] strings without E cannot generate E in result",
- "bson": "18000000136400185C0ACE0000000000000000000038B000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0345678.5432\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-345678.5432\"}}"
- },
- {
- "description": "[basx064] strings without E cannot generate E in result",
- "bson": "18000000136400185C0ACE0000000000000000000038B000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-345678.5432\"}}"
- },
- {
- "description": "[basx041] strings without E cannot generate E in result",
- "bson": "180000001364004C0000000000000000000000000040B000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-76\"}}"
- },
- {
- "description": "[basx027] conform to rules and exponent will be in permitted range).",
- "bson": "180000001364000F270000000000000000000000003AB000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-9.999\"}}"
- },
- {
- "description": "[basx026] conform to rules and exponent will be in permitted range).",
- "bson": "180000001364009F230000000000000000000000003AB000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-9.119\"}}"
- },
- {
- "description": "[basx025] conform to rules and exponent will be in permitted range).",
- "bson": "180000001364008F030000000000000000000000003CB000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-9.11\"}}"
- },
- {
- "description": "[basx024] conform to rules and exponent will be in permitted range).",
- "bson": "180000001364005B000000000000000000000000003EB000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-9.1\"}}"
- },
- {
- "description": "[dqbsr531] negatives (Rounded)",
- "bson": "1800000013640099761CC7B548F377DC80A131C836FEAF00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-1.1111111111111111111111111111123450\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-1.111111111111111111111111111112345\"}}"
- },
- {
- "description": "[basx022] conform to rules and exponent will be in permitted range).",
- "bson": "180000001364000A000000000000000000000000003EB000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-1.0\"}}"
- },
- {
- "description": "[basx021] conform to rules and exponent will be in permitted range).",
- "bson": "18000000136400010000000000000000000000000040B000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-1\"}}"
- },
- {
- "description": "[basx601] Zeros",
- "bson": "1800000013640000000000000000000000000000002E3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000000000\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-9\"}}"
- },
- {
- "description": "[basx622] Zeros",
- "bson": "1800000013640000000000000000000000000000002EB000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.000000000\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E-9\"}}"
- },
- {
- "description": "[basx602] Zeros",
- "bson": "180000001364000000000000000000000000000000303000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00000000\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-8\"}}"
- },
- {
- "description": "[basx621] Zeros",
- "bson": "18000000136400000000000000000000000000000030B000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.00000000\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E-8\"}}"
- },
- {
- "description": "[basx603] Zeros",
- "bson": "180000001364000000000000000000000000000000323000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0000000\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-7\"}}"
- },
- {
- "description": "[basx620] Zeros",
- "bson": "18000000136400000000000000000000000000000032B000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.0000000\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E-7\"}}"
- },
- {
- "description": "[basx604] Zeros",
- "bson": "180000001364000000000000000000000000000000343000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000000\"}}"
- },
- {
- "description": "[basx619] Zeros",
- "bson": "18000000136400000000000000000000000000000034B000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.000000\"}}"
- },
- {
- "description": "[basx605] Zeros",
- "bson": "180000001364000000000000000000000000000000363000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00000\"}}"
- },
- {
- "description": "[basx618] Zeros",
- "bson": "18000000136400000000000000000000000000000036B000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.00000\"}}"
- },
- {
- "description": "[basx680] Zeros",
- "bson": "180000001364000000000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"000000.\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0\"}}"
- },
- {
- "description": "[basx606] Zeros",
- "bson": "180000001364000000000000000000000000000000383000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0000\"}}"
- },
- {
- "description": "[basx617] Zeros",
- "bson": "18000000136400000000000000000000000000000038B000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.0000\"}}"
- },
- {
- "description": "[basx681] Zeros",
- "bson": "180000001364000000000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"00000.\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0\"}}"
- },
- {
- "description": "[basx686] Zeros",
- "bson": "180000001364000000000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"+00000.\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0\"}}"
- },
- {
- "description": "[basx687] Zeros",
- "bson": "18000000136400000000000000000000000000000040B000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-00000.\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0\"}}"
- },
- {
- "description": "[basx019] conform to rules and exponent will be in permitted range).",
- "bson": "1800000013640000000000000000000000000000003CB000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-00.00\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.00\"}}"
- },
- {
- "description": "[basx607] Zeros",
- "bson": "1800000013640000000000000000000000000000003A3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000\"}}"
- },
- {
- "description": "[basx616] Zeros",
- "bson": "1800000013640000000000000000000000000000003AB000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.000\"}}"
- },
- {
- "description": "[basx682] Zeros",
- "bson": "180000001364000000000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0000.\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0\"}}"
- },
- {
- "description": "[basx155] Numbers with E",
- "bson": "1800000013640000000000000000000000000000003A3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000e+0\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000\"}}"
- },
- {
- "description": "[basx130] Numbers with E",
- "bson": "180000001364000000000000000000000000000000383000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000E-1\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0000\"}}"
- },
- {
- "description": "[basx290] some more negative zeros [systematic tests below]",
- "bson": "18000000136400000000000000000000000000000038B000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.000E-1\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.0000\"}}"
- },
- {
- "description": "[basx131] Numbers with E",
- "bson": "180000001364000000000000000000000000000000363000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000E-2\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00000\"}}"
- },
- {
- "description": "[basx291] some more negative zeros [systematic tests below]",
- "bson": "18000000136400000000000000000000000000000036B000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.000E-2\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.00000\"}}"
- },
- {
- "description": "[basx132] Numbers with E",
- "bson": "180000001364000000000000000000000000000000343000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000E-3\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000000\"}}"
- },
- {
- "description": "[basx292] some more negative zeros [systematic tests below]",
- "bson": "18000000136400000000000000000000000000000034B000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.000E-3\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.000000\"}}"
- },
- {
- "description": "[basx133] Numbers with E",
- "bson": "180000001364000000000000000000000000000000323000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000E-4\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-7\"}}"
- },
- {
- "description": "[basx293] some more negative zeros [systematic tests below]",
- "bson": "18000000136400000000000000000000000000000032B000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.000E-4\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E-7\"}}"
- },
- {
- "description": "[basx608] Zeros",
- "bson": "1800000013640000000000000000000000000000003C3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00\"}}"
- },
- {
- "description": "[basx615] Zeros",
- "bson": "1800000013640000000000000000000000000000003CB000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.00\"}}"
- },
- {
- "description": "[basx683] Zeros",
- "bson": "180000001364000000000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"000.\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0\"}}"
- },
- {
- "description": "[basx630] Zeros",
- "bson": "1800000013640000000000000000000000000000003C3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E+0\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00\"}}"
- },
- {
- "description": "[basx670] Zeros",
- "bson": "1800000013640000000000000000000000000000003C3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E-0\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00\"}}"
- },
- {
- "description": "[basx631] Zeros",
- "bson": "1800000013640000000000000000000000000000003E3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E+1\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0\"}}"
- },
- {
- "description": "[basx671] Zeros",
- "bson": "1800000013640000000000000000000000000000003A3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E-1\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000\"}}"
- },
- {
- "description": "[basx134] Numbers with E",
- "bson": "180000001364000000000000000000000000000000383000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E-2\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0000\"}}"
- },
- {
- "description": "[basx294] some more negative zeros [systematic tests below]",
- "bson": "18000000136400000000000000000000000000000038B000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.00E-2\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.0000\"}}"
- },
- {
- "description": "[basx632] Zeros",
- "bson": "180000001364000000000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E+2\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0\"}}"
- },
- {
- "description": "[basx672] Zeros",
- "bson": "180000001364000000000000000000000000000000383000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E-2\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0000\"}}"
- },
- {
- "description": "[basx135] Numbers with E",
- "bson": "180000001364000000000000000000000000000000363000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E-3\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00000\"}}"
- },
- {
- "description": "[basx295] some more negative zeros [systematic tests below]",
- "bson": "18000000136400000000000000000000000000000036B000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.00E-3\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.00000\"}}"
- },
- {
- "description": "[basx633] Zeros",
- "bson": "180000001364000000000000000000000000000000423000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E+3\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+1\"}}"
- },
- {
- "description": "[basx673] Zeros",
- "bson": "180000001364000000000000000000000000000000363000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E-3\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00000\"}}"
- },
- {
- "description": "[basx136] Numbers with E",
- "bson": "180000001364000000000000000000000000000000343000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E-4\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000000\"}}"
- },
- {
- "description": "[basx674] Zeros",
- "bson": "180000001364000000000000000000000000000000343000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E-4\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000000\"}}"
- },
- {
- "description": "[basx634] Zeros",
- "bson": "180000001364000000000000000000000000000000443000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E+4\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+2\"}}"
- },
- {
- "description": "[basx137] Numbers with E",
- "bson": "180000001364000000000000000000000000000000323000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E-5\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-7\"}}"
- },
- {
- "description": "[basx635] Zeros",
- "bson": "180000001364000000000000000000000000000000463000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E+5\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+3\"}}"
- },
- {
- "description": "[basx675] Zeros",
- "bson": "180000001364000000000000000000000000000000323000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E-5\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-7\"}}"
- },
- {
- "description": "[basx636] Zeros",
- "bson": "180000001364000000000000000000000000000000483000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E+6\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+4\"}}"
- },
- {
- "description": "[basx676] Zeros",
- "bson": "180000001364000000000000000000000000000000303000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E-6\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-8\"}}"
- },
- {
- "description": "[basx637] Zeros",
- "bson": "1800000013640000000000000000000000000000004A3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E+7\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+5\"}}"
- },
- {
- "description": "[basx677] Zeros",
- "bson": "1800000013640000000000000000000000000000002E3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E-7\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-9\"}}"
- },
- {
- "description": "[basx638] Zeros",
- "bson": "1800000013640000000000000000000000000000004C3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E+8\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+6\"}}"
- },
- {
- "description": "[basx678] Zeros",
- "bson": "1800000013640000000000000000000000000000002C3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E-8\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-10\"}}"
- },
- {
- "description": "[basx149] Numbers with E",
- "bson": "180000001364000000000000000000000000000000523000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"000E+9\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+9\"}}"
- },
- {
- "description": "[basx639] Zeros",
- "bson": "1800000013640000000000000000000000000000004E3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E+9\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+7\"}}"
- },
- {
- "description": "[basx679] Zeros",
- "bson": "1800000013640000000000000000000000000000002A3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E-9\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-11\"}}"
- },
- {
- "description": "[basx063] strings without E cannot generate E in result",
- "bson": "18000000136400185C0ACE00000000000000000000383000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"+00345678.5432\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"345678.5432\"}}"
- },
- {
- "description": "[basx018] conform to rules and exponent will be in permitted range).",
- "bson": "1800000013640000000000000000000000000000003EB000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.0\"}}"
- },
- {
- "description": "[basx609] Zeros",
- "bson": "1800000013640000000000000000000000000000003E3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0\"}}"
- },
- {
- "description": "[basx614] Zeros",
- "bson": "1800000013640000000000000000000000000000003EB000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.0\"}}"
- },
- {
- "description": "[basx684] Zeros",
- "bson": "180000001364000000000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"00.\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0\"}}"
- },
- {
- "description": "[basx640] Zeros",
- "bson": "1800000013640000000000000000000000000000003E3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0E+0\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0\"}}"
- },
- {
- "description": "[basx660] Zeros",
- "bson": "1800000013640000000000000000000000000000003E3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0E-0\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0\"}}"
- },
- {
- "description": "[basx641] Zeros",
- "bson": "180000001364000000000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0E+1\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0\"}}"
- },
- {
- "description": "[basx661] Zeros",
- "bson": "1800000013640000000000000000000000000000003C3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0E-1\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00\"}}"
- },
- {
- "description": "[basx296] some more negative zeros [systematic tests below]",
- "bson": "1800000013640000000000000000000000000000003AB000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.0E-2\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.000\"}}"
- },
- {
- "description": "[basx642] Zeros",
- "bson": "180000001364000000000000000000000000000000423000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0E+2\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+1\"}}"
- },
- {
- "description": "[basx662] Zeros",
- "bson": "1800000013640000000000000000000000000000003A3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0E-2\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000\"}}"
- },
- {
- "description": "[basx297] some more negative zeros [systematic tests below]",
- "bson": "18000000136400000000000000000000000000000038B000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.0E-3\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.0000\"}}"
- },
- {
- "description": "[basx643] Zeros",
- "bson": "180000001364000000000000000000000000000000443000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0E+3\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+2\"}}"
- },
- {
- "description": "[basx663] Zeros",
- "bson": "180000001364000000000000000000000000000000383000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0E-3\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0000\"}}"
- },
- {
- "description": "[basx644] Zeros",
- "bson": "180000001364000000000000000000000000000000463000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0E+4\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+3\"}}"
- },
- {
- "description": "[basx664] Zeros",
- "bson": "180000001364000000000000000000000000000000363000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0E-4\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00000\"}}"
- },
- {
- "description": "[basx645] Zeros",
- "bson": "180000001364000000000000000000000000000000483000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0E+5\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+4\"}}"
- },
- {
- "description": "[basx665] Zeros",
- "bson": "180000001364000000000000000000000000000000343000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0E-5\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000000\"}}"
- },
- {
- "description": "[basx646] Zeros",
- "bson": "1800000013640000000000000000000000000000004A3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0E+6\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+5\"}}"
- },
- {
- "description": "[basx666] Zeros",
- "bson": "180000001364000000000000000000000000000000323000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0E-6\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-7\"}}"
- },
- {
- "description": "[basx647] Zeros",
- "bson": "1800000013640000000000000000000000000000004C3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0E+7\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+6\"}}"
- },
- {
- "description": "[basx667] Zeros",
- "bson": "180000001364000000000000000000000000000000303000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0E-7\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-8\"}}"
- },
- {
- "description": "[basx648] Zeros",
- "bson": "1800000013640000000000000000000000000000004E3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0E+8\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+7\"}}"
- },
- {
- "description": "[basx668] Zeros",
- "bson": "1800000013640000000000000000000000000000002E3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0E-8\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-9\"}}"
- },
- {
- "description": "[basx160] Numbers with E",
- "bson": "180000001364000000000000000000000000000000523000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"00E+9\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+9\"}}"
- },
- {
- "description": "[basx161] Numbers with E",
- "bson": "1800000013640000000000000000000000000000002E3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"00E-9\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-9\"}}"
- },
- {
- "description": "[basx649] Zeros",
- "bson": "180000001364000000000000000000000000000000503000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0E+9\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+8\"}}"
- },
- {
- "description": "[basx669] Zeros",
- "bson": "1800000013640000000000000000000000000000002C3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0E-9\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-10\"}}"
- },
- {
- "description": "[basx062] strings without E cannot generate E in result",
- "bson": "18000000136400185C0ACE00000000000000000000383000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"+0345678.5432\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"345678.5432\"}}"
- },
- {
- "description": "[basx001] conform to rules and exponent will be in permitted range).",
- "bson": "180000001364000000000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0\"}}"
- },
- {
- "description": "[basx017] conform to rules and exponent will be in permitted range).",
- "bson": "18000000136400000000000000000000000000000040B000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0\"}}"
- },
- {
- "description": "[basx611] Zeros",
- "bson": "180000001364000000000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0\"}}"
- },
- {
- "description": "[basx613] Zeros",
- "bson": "18000000136400000000000000000000000000000040B000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0\"}}"
- },
- {
- "description": "[basx685] Zeros",
- "bson": "180000001364000000000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0\"}}"
- },
- {
- "description": "[basx688] Zeros",
- "bson": "180000001364000000000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"+0.\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0\"}}"
- },
- {
- "description": "[basx689] Zeros",
- "bson": "18000000136400000000000000000000000000000040B000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0\"}}"
- },
- {
- "description": "[basx650] Zeros",
- "bson": "180000001364000000000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+0\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0\"}}"
- },
- {
- "description": "[basx651] Zeros",
- "bson": "180000001364000000000000000000000000000000423000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+1\"}}"
- },
- {
- "description": "[basx298] some more negative zeros [systematic tests below]",
- "bson": "1800000013640000000000000000000000000000003CB000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E-2\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.00\"}}"
- },
- {
- "description": "[basx652] Zeros",
- "bson": "180000001364000000000000000000000000000000443000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+2\"}}"
- },
- {
- "description": "[basx299] some more negative zeros [systematic tests below]",
- "bson": "1800000013640000000000000000000000000000003AB000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E-3\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.000\"}}"
- },
- {
- "description": "[basx653] Zeros",
- "bson": "180000001364000000000000000000000000000000463000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+3\"}}"
- },
- {
- "description": "[basx654] Zeros",
- "bson": "180000001364000000000000000000000000000000483000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+4\"}}"
- },
- {
- "description": "[basx655] Zeros",
- "bson": "1800000013640000000000000000000000000000004A3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+5\"}}"
- },
- {
- "description": "[basx656] Zeros",
- "bson": "1800000013640000000000000000000000000000004C3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+6\"}}"
- },
- {
- "description": "[basx657] Zeros",
- "bson": "1800000013640000000000000000000000000000004E3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+7\"}}"
- },
- {
- "description": "[basx658] Zeros",
- "bson": "180000001364000000000000000000000000000000503000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+8\"}}"
- },
- {
- "description": "[basx138] Numbers with E",
- "bson": "180000001364000000000000000000000000000000523000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"+0E+9\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+9\"}}"
- },
- {
- "description": "[basx139] Numbers with E",
- "bson": "18000000136400000000000000000000000000000052B000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E+9\"}}"
- },
- {
- "description": "[basx144] Numbers with E",
- "bson": "180000001364000000000000000000000000000000523000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+9\"}}"
- },
- {
- "description": "[basx154] Numbers with E",
- "bson": "180000001364000000000000000000000000000000523000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0E9\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+9\"}}"
- },
- {
- "description": "[basx659] Zeros",
- "bson": "180000001364000000000000000000000000000000523000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+9\"}}"
- },
- {
- "description": "[basx042] strings without E cannot generate E in result",
- "bson": "18000000136400FC040000000000000000000000003C3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"+12.76\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"12.76\"}}"
- },
- {
- "description": "[basx143] Numbers with E",
- "bson": "180000001364000100000000000000000000000000523000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"+1E+009\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+9\"}}"
- },
- {
- "description": "[basx061] strings without E cannot generate E in result",
- "bson": "18000000136400185C0ACE00000000000000000000383000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"+345678.5432\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"345678.5432\"}}"
- },
- {
- "description": "[basx036] conform to rules and exponent will be in permitted range).",
- "bson": "1800000013640015CD5B0700000000000000000000203000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0000000123456789\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.23456789E-8\"}}"
- },
- {
- "description": "[basx035] conform to rules and exponent will be in permitted range).",
- "bson": "1800000013640015CD5B0700000000000000000000223000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000000123456789\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.23456789E-7\"}}"
- },
- {
- "description": "[basx034] conform to rules and exponent will be in permitted range).",
- "bson": "1800000013640015CD5B0700000000000000000000243000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00000123456789\"}}"
- },
- {
- "description": "[basx053] strings without E cannot generate E in result",
- "bson": "180000001364003200000000000000000000000000323000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0000050\"}}"
- },
- {
- "description": "[basx033] conform to rules and exponent will be in permitted range).",
- "bson": "1800000013640015CD5B0700000000000000000000263000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0000123456789\"}}"
- },
- {
- "description": "[basx016] conform to rules and exponent will be in permitted range).",
- "bson": "180000001364000C000000000000000000000000003A3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.012\"}}"
- },
- {
- "description": "[basx015] conform to rules and exponent will be in permitted range).",
- "bson": "180000001364007B000000000000000000000000003A3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.123\"}}"
- },
- {
- "description": "[basx037] conform to rules and exponent will be in permitted range).",
- "bson": "1800000013640078DF0D8648700000000000000000223000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.123456789012344\"}}"
- },
- {
- "description": "[basx038] conform to rules and exponent will be in permitted range).",
- "bson": "1800000013640079DF0D8648700000000000000000223000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.123456789012345\"}}"
- },
- {
- "description": "[basx250] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000383000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1265\"}}"
- },
- {
- "description": "[basx257] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000383000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1265E-0\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1265\"}}"
- },
- {
- "description": "[basx256] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000363000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1265E-1\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.01265\"}}"
- },
- {
- "description": "[basx258] Numbers with E",
- "bson": "18000000136400F1040000000000000000000000003A3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1265E+1\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265\"}}"
- },
- {
- "description": "[basx251] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000103000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1265E-20\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E-21\"}}"
- },
- {
- "description": "[basx263] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000603000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1265E+20\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+19\"}}"
- },
- {
- "description": "[basx255] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000343000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1265E-2\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.001265\"}}"
- },
- {
- "description": "[basx259] Numbers with E",
- "bson": "18000000136400F1040000000000000000000000003C3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1265E+2\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"12.65\"}}"
- },
- {
- "description": "[basx254] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000323000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1265E-3\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0001265\"}}"
- },
- {
- "description": "[basx260] Numbers with E",
- "bson": "18000000136400F1040000000000000000000000003E3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1265E+3\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"126.5\"}}"
- },
- {
- "description": "[basx253] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000303000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1265E-4\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00001265\"}}"
- },
- {
- "description": "[basx261] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1265E+4\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1265\"}}"
- },
- {
- "description": "[basx252] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000283000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1265E-8\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E-9\"}}"
- },
- {
- "description": "[basx262] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000483000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1265E+8\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+7\"}}"
- },
- {
- "description": "[basx159] Numbers with E",
- "bson": "1800000013640049000000000000000000000000002E3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.73e-7\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"7.3E-8\"}}"
- },
- {
- "description": "[basx004] conform to rules and exponent will be in permitted range).",
- "bson": "1800000013640064000000000000000000000000003C3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00\"}}"
- },
- {
- "description": "[basx003] conform to rules and exponent will be in permitted range).",
- "bson": "180000001364000A000000000000000000000000003E3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0\"}}"
- },
- {
- "description": "[basx002] conform to rules and exponent will be in permitted range).",
- "bson": "180000001364000100000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1\"}}"
- },
- {
- "description": "[basx148] Numbers with E",
- "bson": "180000001364000100000000000000000000000000523000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+009\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+9\"}}"
- },
- {
- "description": "[basx153] Numbers with E",
- "bson": "180000001364000100000000000000000000000000523000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E009\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+9\"}}"
- },
- {
- "description": "[basx141] Numbers with E",
- "bson": "180000001364000100000000000000000000000000523000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1e+09\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+9\"}}"
- },
- {
- "description": "[basx146] Numbers with E",
- "bson": "180000001364000100000000000000000000000000523000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+09\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+9\"}}"
- },
- {
- "description": "[basx151] Numbers with E",
- "bson": "180000001364000100000000000000000000000000523000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1e09\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+9\"}}"
- },
- {
- "description": "[basx142] Numbers with E",
- "bson": "180000001364000100000000000000000000000000F43000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+90\"}}"
- },
- {
- "description": "[basx147] Numbers with E",
- "bson": "180000001364000100000000000000000000000000F43000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1e+90\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+90\"}}"
- },
- {
- "description": "[basx152] Numbers with E",
- "bson": "180000001364000100000000000000000000000000F43000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E90\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+90\"}}"
- },
- {
- "description": "[basx140] Numbers with E",
- "bson": "180000001364000100000000000000000000000000523000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+9\"}}"
- },
- {
- "description": "[basx150] Numbers with E",
- "bson": "180000001364000100000000000000000000000000523000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E9\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+9\"}}"
- },
- {
- "description": "[basx014] conform to rules and exponent will be in permitted range).",
- "bson": "18000000136400D2040000000000000000000000003A3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.234\"}}"
- },
- {
- "description": "[basx170] Numbers with E",
- "bson": "18000000136400F1040000000000000000000000003A3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265\"}}"
- },
- {
- "description": "[basx177] Numbers with E",
- "bson": "18000000136400F1040000000000000000000000003A3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E-0\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265\"}}"
- },
- {
- "description": "[basx176] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000383000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E-1\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1265\"}}"
- },
- {
- "description": "[basx178] Numbers with E",
- "bson": "18000000136400F1040000000000000000000000003C3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+1\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"12.65\"}}"
- },
- {
- "description": "[basx171] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000123000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E-20\"}}"
- },
- {
- "description": "[basx183] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000623000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+20\"}}"
- },
- {
- "description": "[basx175] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000363000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E-2\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.01265\"}}"
- },
- {
- "description": "[basx179] Numbers with E",
- "bson": "18000000136400F1040000000000000000000000003E3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+2\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"126.5\"}}"
- },
- {
- "description": "[basx174] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000343000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E-3\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.001265\"}}"
- },
- {
- "description": "[basx180] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+3\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1265\"}}"
- },
- {
- "description": "[basx173] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000323000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E-4\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0001265\"}}"
- },
- {
- "description": "[basx181] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000423000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+4\"}}"
- },
- {
- "description": "[basx172] Numbers with E",
- "bson": "18000000136400F1040000000000000000000000002A3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E-8\"}}"
- },
- {
- "description": "[basx182] Numbers with E",
- "bson": "18000000136400F1040000000000000000000000004A3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+8\"}}"
- },
- {
- "description": "[basx157] Numbers with E",
- "bson": "180000001364000400000000000000000000000000523000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"4E+9\"}}"
- },
- {
- "description": "[basx067] examples",
- "bson": "180000001364000500000000000000000000000000343000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"5E-6\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000005\"}}"
- },
- {
- "description": "[basx069] examples",
- "bson": "180000001364000500000000000000000000000000323000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"5E-7\"}}"
- },
- {
- "description": "[basx385] Engineering notation tests",
- "bson": "180000001364000700000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"7E0\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"7\"}}"
- },
- {
- "description": "[basx365] Engineering notation tests",
- "bson": "180000001364000700000000000000000000000000543000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"7E10\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E+10\"}}"
- },
- {
- "description": "[basx405] Engineering notation tests",
- "bson": "1800000013640007000000000000000000000000002C3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"7E-10\"}}"
- },
- {
- "description": "[basx363] Engineering notation tests",
- "bson": "180000001364000700000000000000000000000000563000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"7E11\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E+11\"}}"
- },
- {
- "description": "[basx407] Engineering notation tests",
- "bson": "1800000013640007000000000000000000000000002A3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"7E-11\"}}"
- },
- {
- "description": "[basx361] Engineering notation tests",
- "bson": "180000001364000700000000000000000000000000583000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"7E12\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E+12\"}}"
- },
- {
- "description": "[basx409] Engineering notation tests",
- "bson": "180000001364000700000000000000000000000000283000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"7E-12\"}}"
- },
- {
- "description": "[basx411] Engineering notation tests",
- "bson": "180000001364000700000000000000000000000000263000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"7E-13\"}}"
- },
- {
- "description": "[basx383] Engineering notation tests",
- "bson": "180000001364000700000000000000000000000000423000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"7E1\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E+1\"}}"
- },
- {
- "description": "[basx387] Engineering notation tests",
- "bson": "1800000013640007000000000000000000000000003E3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"7E-1\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.7\"}}"
- },
- {
- "description": "[basx381] Engineering notation tests",
- "bson": "180000001364000700000000000000000000000000443000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"7E2\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E+2\"}}"
- },
- {
- "description": "[basx389] Engineering notation tests",
- "bson": "1800000013640007000000000000000000000000003C3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"7E-2\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.07\"}}"
- },
- {
- "description": "[basx379] Engineering notation tests",
- "bson": "180000001364000700000000000000000000000000463000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"7E3\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E+3\"}}"
- },
- {
- "description": "[basx391] Engineering notation tests",
- "bson": "1800000013640007000000000000000000000000003A3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"7E-3\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.007\"}}"
- },
- {
- "description": "[basx377] Engineering notation tests",
- "bson": "180000001364000700000000000000000000000000483000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"7E4\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E+4\"}}"
- },
- {
- "description": "[basx393] Engineering notation tests",
- "bson": "180000001364000700000000000000000000000000383000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"7E-4\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0007\"}}"
- },
- {
- "description": "[basx375] Engineering notation tests",
- "bson": "1800000013640007000000000000000000000000004A3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"7E5\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E+5\"}}"
- },
- {
- "description": "[basx395] Engineering notation tests",
- "bson": "180000001364000700000000000000000000000000363000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"7E-5\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00007\"}}"
- },
- {
- "description": "[basx373] Engineering notation tests",
- "bson": "1800000013640007000000000000000000000000004C3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"7E6\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E+6\"}}"
- },
- {
- "description": "[basx397] Engineering notation tests",
- "bson": "180000001364000700000000000000000000000000343000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"7E-6\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000007\"}}"
- },
- {
- "description": "[basx371] Engineering notation tests",
- "bson": "1800000013640007000000000000000000000000004E3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"7E7\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E+7\"}}"
- },
- {
- "description": "[basx399] Engineering notation tests",
- "bson": "180000001364000700000000000000000000000000323000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"7E-7\"}}"
- },
- {
- "description": "[basx369] Engineering notation tests",
- "bson": "180000001364000700000000000000000000000000503000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"7E8\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E+8\"}}"
- },
- {
- "description": "[basx401] Engineering notation tests",
- "bson": "180000001364000700000000000000000000000000303000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"7E-8\"}}"
- },
- {
- "description": "[basx367] Engineering notation tests",
- "bson": "180000001364000700000000000000000000000000523000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"7E9\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E+9\"}}"
- },
- {
- "description": "[basx403] Engineering notation tests",
- "bson": "1800000013640007000000000000000000000000002E3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"7E-9\"}}"
- },
- {
- "description": "[basx007] conform to rules and exponent will be in permitted range).",
- "bson": "1800000013640064000000000000000000000000003E3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"10.0\"}}"
- },
- {
- "description": "[basx005] conform to rules and exponent will be in permitted range).",
- "bson": "180000001364000A00000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"10\"}}"
- },
- {
- "description": "[basx165] Numbers with E",
- "bson": "180000001364000A00000000000000000000000000523000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"10E+009\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E+10\"}}"
- },
- {
- "description": "[basx163] Numbers with E",
- "bson": "180000001364000A00000000000000000000000000523000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"10E+09\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E+10\"}}"
- },
- {
- "description": "[basx325] Engineering notation tests",
- "bson": "180000001364000A00000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"10e0\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"10\"}}"
- },
- {
- "description": "[basx305] Engineering notation tests",
- "bson": "180000001364000A00000000000000000000000000543000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"10e10\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E+11\"}}"
- },
- {
- "description": "[basx345] Engineering notation tests",
- "bson": "180000001364000A000000000000000000000000002C3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"10e-10\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E-9\"}}"
- },
- {
- "description": "[basx303] Engineering notation tests",
- "bson": "180000001364000A00000000000000000000000000563000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"10e11\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E+12\"}}"
- },
- {
- "description": "[basx347] Engineering notation tests",
- "bson": "180000001364000A000000000000000000000000002A3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"10e-11\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E-10\"}}"
- },
- {
- "description": "[basx301] Engineering notation tests",
- "bson": "180000001364000A00000000000000000000000000583000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"10e12\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E+13\"}}"
- },
- {
- "description": "[basx349] Engineering notation tests",
- "bson": "180000001364000A00000000000000000000000000283000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"10e-12\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E-11\"}}"
- },
- {
- "description": "[basx351] Engineering notation tests",
- "bson": "180000001364000A00000000000000000000000000263000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"10e-13\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E-12\"}}"
- },
- {
- "description": "[basx323] Engineering notation tests",
- "bson": "180000001364000A00000000000000000000000000423000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"10e1\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E+2\"}}"
- },
- {
- "description": "[basx327] Engineering notation tests",
- "bson": "180000001364000A000000000000000000000000003E3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"10e-1\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0\"}}"
- },
- {
- "description": "[basx321] Engineering notation tests",
- "bson": "180000001364000A00000000000000000000000000443000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"10e2\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E+3\"}}"
- },
- {
- "description": "[basx329] Engineering notation tests",
- "bson": "180000001364000A000000000000000000000000003C3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"10e-2\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.10\"}}"
- },
- {
- "description": "[basx319] Engineering notation tests",
- "bson": "180000001364000A00000000000000000000000000463000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"10e3\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E+4\"}}"
- },
- {
- "description": "[basx331] Engineering notation tests",
- "bson": "180000001364000A000000000000000000000000003A3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"10e-3\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.010\"}}"
- },
- {
- "description": "[basx317] Engineering notation tests",
- "bson": "180000001364000A00000000000000000000000000483000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"10e4\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E+5\"}}"
- },
- {
- "description": "[basx333] Engineering notation tests",
- "bson": "180000001364000A00000000000000000000000000383000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"10e-4\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0010\"}}"
- },
- {
- "description": "[basx315] Engineering notation tests",
- "bson": "180000001364000A000000000000000000000000004A3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"10e5\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E+6\"}}"
- },
- {
- "description": "[basx335] Engineering notation tests",
- "bson": "180000001364000A00000000000000000000000000363000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"10e-5\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00010\"}}"
- },
- {
- "description": "[basx313] Engineering notation tests",
- "bson": "180000001364000A000000000000000000000000004C3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"10e6\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E+7\"}}"
- },
- {
- "description": "[basx337] Engineering notation tests",
- "bson": "180000001364000A00000000000000000000000000343000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"10e-6\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000010\"}}"
- },
- {
- "description": "[basx311] Engineering notation tests",
- "bson": "180000001364000A000000000000000000000000004E3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"10e7\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E+8\"}}"
- },
- {
- "description": "[basx339] Engineering notation tests",
- "bson": "180000001364000A00000000000000000000000000323000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"10e-7\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0000010\"}}"
- },
- {
- "description": "[basx309] Engineering notation tests",
- "bson": "180000001364000A00000000000000000000000000503000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"10e8\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E+9\"}}"
- },
- {
- "description": "[basx341] Engineering notation tests",
- "bson": "180000001364000A00000000000000000000000000303000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"10e-8\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E-7\"}}"
- },
- {
- "description": "[basx164] Numbers with E",
- "bson": "180000001364000A00000000000000000000000000F43000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"10e+90\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E+91\"}}"
- },
- {
- "description": "[basx162] Numbers with E",
- "bson": "180000001364000A00000000000000000000000000523000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"10E+9\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E+10\"}}"
- },
- {
- "description": "[basx307] Engineering notation tests",
- "bson": "180000001364000A00000000000000000000000000523000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"10e9\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E+10\"}}"
- },
- {
- "description": "[basx343] Engineering notation tests",
- "bson": "180000001364000A000000000000000000000000002E3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"10e-9\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E-8\"}}"
- },
- {
- "description": "[basx008] conform to rules and exponent will be in permitted range).",
- "bson": "1800000013640065000000000000000000000000003E3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"10.1\"}}"
- },
- {
- "description": "[basx009] conform to rules and exponent will be in permitted range).",
- "bson": "1800000013640068000000000000000000000000003E3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"10.4\"}}"
- },
- {
- "description": "[basx010] conform to rules and exponent will be in permitted range).",
- "bson": "1800000013640069000000000000000000000000003E3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"10.5\"}}"
- },
- {
- "description": "[basx011] conform to rules and exponent will be in permitted range).",
- "bson": "180000001364006A000000000000000000000000003E3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"10.6\"}}"
- },
- {
- "description": "[basx012] conform to rules and exponent will be in permitted range).",
- "bson": "180000001364006D000000000000000000000000003E3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"10.9\"}}"
- },
- {
- "description": "[basx013] conform to rules and exponent will be in permitted range).",
- "bson": "180000001364006E000000000000000000000000003E3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"11.0\"}}"
- },
- {
- "description": "[basx040] strings without E cannot generate E in result",
- "bson": "180000001364000C00000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"12\"}}"
- },
- {
- "description": "[basx190] Numbers with E",
- "bson": "18000000136400F1040000000000000000000000003C3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"12.65\"}}"
- },
- {
- "description": "[basx197] Numbers with E",
- "bson": "18000000136400F1040000000000000000000000003C3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"12.65E-0\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"12.65\"}}"
- },
- {
- "description": "[basx196] Numbers with E",
- "bson": "18000000136400F1040000000000000000000000003A3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"12.65E-1\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265\"}}"
- },
- {
- "description": "[basx198] Numbers with E",
- "bson": "18000000136400F1040000000000000000000000003E3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"12.65E+1\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"126.5\"}}"
- },
- {
- "description": "[basx191] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000143000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"12.65E-20\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E-19\"}}"
- },
- {
- "description": "[basx203] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000643000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"12.65E+20\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+21\"}}"
- },
- {
- "description": "[basx195] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000383000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"12.65E-2\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1265\"}}"
- },
- {
- "description": "[basx199] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"12.65E+2\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1265\"}}"
- },
- {
- "description": "[basx194] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000363000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"12.65E-3\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.01265\"}}"
- },
- {
- "description": "[basx200] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000423000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"12.65E+3\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+4\"}}"
- },
- {
- "description": "[basx193] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000343000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"12.65E-4\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.001265\"}}"
- },
- {
- "description": "[basx201] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000443000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"12.65E+4\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+5\"}}"
- },
- {
- "description": "[basx192] Numbers with E",
- "bson": "18000000136400F1040000000000000000000000002C3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"12.65E-8\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E-7\"}}"
- },
- {
- "description": "[basx202] Numbers with E",
- "bson": "18000000136400F1040000000000000000000000004C3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"12.65E+8\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+9\"}}"
- },
- {
- "description": "[basx044] strings without E cannot generate E in result",
- "bson": "18000000136400FC040000000000000000000000003C3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"012.76\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"12.76\"}}"
- },
- {
- "description": "[basx042] strings without E cannot generate E in result",
- "bson": "18000000136400FC040000000000000000000000003C3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"12.76\"}}"
- },
- {
- "description": "[basx046] strings without E cannot generate E in result",
- "bson": "180000001364001100000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"17.\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"17\"}}"
- },
- {
- "description": "[basx049] strings without E cannot generate E in result",
- "bson": "180000001364002C00000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0044\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"44\"}}"
- },
- {
- "description": "[basx048] strings without E cannot generate E in result",
- "bson": "180000001364002C00000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"044\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"44\"}}"
- },
- {
- "description": "[basx158] Numbers with E",
- "bson": "180000001364002C00000000000000000000000000523000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"44E+9\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"4.4E+10\"}}"
- },
- {
- "description": "[basx068] examples",
- "bson": "180000001364003200000000000000000000000000323000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"50E-7\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0000050\"}}"
- },
- {
- "description": "[basx169] Numbers with E",
- "bson": "180000001364006400000000000000000000000000523000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"100e+009\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00E+11\"}}"
- },
- {
- "description": "[basx167] Numbers with E",
- "bson": "180000001364006400000000000000000000000000523000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"100e+09\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00E+11\"}}"
- },
- {
- "description": "[basx168] Numbers with E",
- "bson": "180000001364006400000000000000000000000000F43000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"100E+90\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00E+92\"}}"
- },
- {
- "description": "[basx166] Numbers with E",
- "bson": "180000001364006400000000000000000000000000523000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"100e+9\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00E+11\"}}"
- },
- {
- "description": "[basx210] Numbers with E",
- "bson": "18000000136400F1040000000000000000000000003E3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"126.5\"}}"
- },
- {
- "description": "[basx217] Numbers with E",
- "bson": "18000000136400F1040000000000000000000000003E3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"126.5E-0\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"126.5\"}}"
- },
- {
- "description": "[basx216] Numbers with E",
- "bson": "18000000136400F1040000000000000000000000003C3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"126.5E-1\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"12.65\"}}"
- },
- {
- "description": "[basx218] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"126.5E+1\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1265\"}}"
- },
- {
- "description": "[basx211] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000163000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"126.5E-20\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E-18\"}}"
- },
- {
- "description": "[basx223] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000663000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"126.5E+20\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+22\"}}"
- },
- {
- "description": "[basx215] Numbers with E",
- "bson": "18000000136400F1040000000000000000000000003A3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"126.5E-2\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265\"}}"
- },
- {
- "description": "[basx219] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000423000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"126.5E+2\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+4\"}}"
- },
- {
- "description": "[basx214] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000383000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"126.5E-3\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1265\"}}"
- },
- {
- "description": "[basx220] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000443000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"126.5E+3\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+5\"}}"
- },
- {
- "description": "[basx213] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000363000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"126.5E-4\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.01265\"}}"
- },
- {
- "description": "[basx221] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000463000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"126.5E+4\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+6\"}}"
- },
- {
- "description": "[basx212] Numbers with E",
- "bson": "18000000136400F1040000000000000000000000002E3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"126.5E-8\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000001265\"}}"
- },
- {
- "description": "[basx222] Numbers with E",
- "bson": "18000000136400F1040000000000000000000000004E3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"126.5E+8\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+10\"}}"
- },
- {
- "description": "[basx006] conform to rules and exponent will be in permitted range).",
- "bson": "18000000136400E803000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1000\"}}"
- },
- {
- "description": "[basx230] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1265\"}}"
- },
- {
- "description": "[basx237] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1265E-0\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1265\"}}"
- },
- {
- "description": "[basx236] Numbers with E",
- "bson": "18000000136400F1040000000000000000000000003E3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1265E-1\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"126.5\"}}"
- },
- {
- "description": "[basx238] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000423000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1265E+1\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+4\"}}"
- },
- {
- "description": "[basx231] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000183000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1265E-20\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E-17\"}}"
- },
- {
- "description": "[basx243] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000683000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1265E+20\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+23\"}}"
- },
- {
- "description": "[basx235] Numbers with E",
- "bson": "18000000136400F1040000000000000000000000003C3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1265E-2\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"12.65\"}}"
- },
- {
- "description": "[basx239] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000443000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1265E+2\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+5\"}}"
- },
- {
- "description": "[basx234] Numbers with E",
- "bson": "18000000136400F1040000000000000000000000003A3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1265E-3\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265\"}}"
- },
- {
- "description": "[basx240] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000463000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1265E+3\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+6\"}}"
- },
- {
- "description": "[basx233] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000383000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1265E-4\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1265\"}}"
- },
- {
- "description": "[basx241] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000483000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1265E+4\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+7\"}}"
- },
- {
- "description": "[basx232] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000303000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1265E-8\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00001265\"}}"
- },
- {
- "description": "[basx242] Numbers with E",
- "bson": "18000000136400F104000000000000000000000000503000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1265E+8\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+11\"}}"
- },
- {
- "description": "[basx060] strings without E cannot generate E in result",
- "bson": "18000000136400185C0ACE00000000000000000000383000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"345678.5432\"}}"
- },
- {
- "description": "[basx059] strings without E cannot generate E in result",
- "bson": "18000000136400F198670C08000000000000000000363000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0345678.54321\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"345678.54321\"}}"
- },
- {
- "description": "[basx058] strings without E cannot generate E in result",
- "bson": "180000001364006AF90B7C50000000000000000000343000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"345678.543210\"}}"
- },
- {
- "description": "[basx057] strings without E cannot generate E in result",
- "bson": "180000001364006A19562522020000000000000000343000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"2345678.543210\"}}"
- },
- {
- "description": "[basx056] strings without E cannot generate E in result",
- "bson": "180000001364006AB9C8733A0B0000000000000000343000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"12345678.543210\"}}"
- },
- {
- "description": "[basx031] conform to rules and exponent will be in permitted range).",
- "bson": "1800000013640040AF0D8648700000000000000000343000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"123456789.000000\"}}"
- },
- {
- "description": "[basx030] conform to rules and exponent will be in permitted range).",
- "bson": "1800000013640080910F8648700000000000000000343000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"123456789.123456\"}}"
- },
- {
- "description": "[basx032] conform to rules and exponent will be in permitted range).",
- "bson": "1800000013640080910F8648700000000000000000403000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"123456789123456\"}}"
- }
- ]
-}
-`},
-
- {"decimal128-4.json", `
-{
- "description": "Decimal128",
- "bson_type": "0x13",
- "test_key": "d",
- "valid": [
- {
- "description": "[basx023] conform to rules and exponent will be in permitted range).",
- "bson": "1800000013640001000000000000000000000000003EB000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.1\"}}"
- },
-
- {
- "description": "[basx045] strings without E cannot generate E in result",
- "bson": "1800000013640003000000000000000000000000003A3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"+0.003\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.003\"}}"
- },
- {
- "description": "[basx610] Zeros",
- "bson": "1800000013640000000000000000000000000000003E3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \".0\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0\"}}"
- },
- {
- "description": "[basx612] Zeros",
- "bson": "1800000013640000000000000000000000000000003EB000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-.0\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.0\"}}"
- },
- {
- "description": "[basx043] strings without E cannot generate E in result",
- "bson": "18000000136400FC040000000000000000000000003C3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"+12.76\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"12.76\"}}"
- },
- {
- "description": "[basx055] strings without E cannot generate E in result",
- "bson": "180000001364000500000000000000000000000000303000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00000005\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"5E-8\"}}"
- },
- {
- "description": "[basx054] strings without E cannot generate E in result",
- "bson": "180000001364000500000000000000000000000000323000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0000005\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"5E-7\"}}"
- },
- {
- "description": "[basx052] strings without E cannot generate E in result",
- "bson": "180000001364000500000000000000000000000000343000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000005\"}}"
- },
- {
- "description": "[basx051] strings without E cannot generate E in result",
- "bson": "180000001364000500000000000000000000000000363000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"00.00005\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00005\"}}"
- },
- {
- "description": "[basx050] strings without E cannot generate E in result",
- "bson": "180000001364000500000000000000000000000000383000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0005\"}}"
- },
- {
- "description": "[basx047] strings without E cannot generate E in result",
- "bson": "1800000013640005000000000000000000000000003E3000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \".5\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.5\"}}"
- },
- {
- "description": "[dqbsr431] check rounding modes heeded (Rounded)",
- "bson": "1800000013640099761CC7B548F377DC80A131C836FE2F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.1111111111111111111111111111123450\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.111111111111111111111111111112345\"}}"
- },
- {
- "description": "OK2",
- "bson": "18000000136400000000000A5BC138938D44C64D31FC2F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \".100000000000000000000000000000000000000000000000000000000000\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1000000000000000000000000000000000\"}}"
- }
- ],
- "parseErrors": [
- {
- "description": "[basx564] Near-specials (Conversion_syntax)",
- "string": "Infi"
- },
- {
- "description": "[basx565] Near-specials (Conversion_syntax)",
- "string": "Infin"
- },
- {
- "description": "[basx566] Near-specials (Conversion_syntax)",
- "string": "Infini"
- },
- {
- "description": "[basx567] Near-specials (Conversion_syntax)",
- "string": "Infinit"
- },
- {
- "description": "[basx568] Near-specials (Conversion_syntax)",
- "string": "-Infinit"
- },
- {
- "description": "[basx590] some baddies with dots and Es and dots and specials (Conversion_syntax)",
- "string": ".Infinity"
- },
- {
- "description": "[basx562] Near-specials (Conversion_syntax)",
- "string": "NaNq"
- },
- {
- "description": "[basx563] Near-specials (Conversion_syntax)",
- "string": "NaNs"
- },
- {
- "description": "[dqbas939] overflow results at different rounding modes (Overflow & Inexact & Rounded)",
- "string": "-7e10000"
- },
- {
- "description": "[dqbsr534] negatives (Rounded & Inexact)",
- "string": "-1.11111111111111111111111111111234650"
- },
- {
- "description": "[dqbsr535] negatives (Rounded & Inexact)",
- "string": "-1.11111111111111111111111111111234551"
- },
- {
- "description": "[dqbsr533] negatives (Rounded & Inexact)",
- "string": "-1.11111111111111111111111111111234550"
- },
- {
- "description": "[dqbsr532] negatives (Rounded & Inexact)",
- "string": "-1.11111111111111111111111111111234549"
- },
- {
- "description": "[dqbsr432] check rounding modes heeded (Rounded & Inexact)",
- "string": "1.11111111111111111111111111111234549"
- },
- {
- "description": "[dqbsr433] check rounding modes heeded (Rounded & Inexact)",
- "string": "1.11111111111111111111111111111234550"
- },
- {
- "description": "[dqbsr435] check rounding modes heeded (Rounded & Inexact)",
- "string": "1.11111111111111111111111111111234551"
- },
- {
- "description": "[dqbsr434] check rounding modes heeded (Rounded & Inexact)",
- "string": "1.11111111111111111111111111111234650"
- },
- {
- "description": "[dqbas938] overflow results at different rounding modes (Overflow & Inexact & Rounded)",
- "string": "7e10000"
- },
- {
- "description": "Inexact rounding#1",
- "string": "100000000000000000000000000000000000000000000000000000000001"
- },
- {
- "description": "Inexact rounding#2",
- "string": "1E-6177"
- }
- ]
-}
-`},
-
- {"decimal128-5.json", `
-{
- "description": "Decimal128",
- "bson_type": "0x13",
- "test_key": "d",
- "valid": [
- {
- "description": "[decq035] fold-downs (more below) (Clamped)",
- "bson": "18000000136400000000807F1BCF85B27059C8A43CFE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.23E+6144\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.230000000000000000000000000000000E+6144\"}}"
- },
- {
- "description": "[decq037] fold-downs (more below) (Clamped)",
- "bson": "18000000136400000000000A5BC138938D44C64D31FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6144\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000000000000000000000000E+6144\"}}"
- },
- {
- "description": "[decq077] Nmin and below (Subnormal)",
- "bson": "180000001364000000000081EFAC855B416D2DEE04000000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.100000000000000000000000000000000E-6143\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000000000000000000000000000000E-6144\"}}"
- },
- {
- "description": "[decq078] Nmin and below (Subnormal)",
- "bson": "180000001364000000000081EFAC855B416D2DEE04000000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000000000000000000000000000000E-6144\"}}"
- },
- {
- "description": "[decq079] Nmin and below (Subnormal)",
- "bson": "180000001364000A00000000000000000000000000000000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000000000000000000000000000000010E-6143\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E-6175\"}}"
- },
- {
- "description": "[decq080] Nmin and below (Subnormal)",
- "bson": "180000001364000A00000000000000000000000000000000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E-6175\"}}"
- },
- {
- "description": "[decq081] Nmin and below (Subnormal)",
- "bson": "180000001364000100000000000000000000000000020000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00000000000000000000000000000001E-6143\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E-6175\"}}"
- },
- {
- "description": "[decq082] Nmin and below (Subnormal)",
- "bson": "180000001364000100000000000000000000000000020000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E-6175\"}}"
- },
- {
- "description": "[decq083] Nmin and below (Subnormal)",
- "bson": "180000001364000100000000000000000000000000000000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000000000000000000000000000000001E-6143\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E-6176\"}}"
- },
- {
- "description": "[decq084] Nmin and below (Subnormal)",
- "bson": "180000001364000100000000000000000000000000000000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E-6176\"}}"
- },
- {
- "description": "[decq090] underflows cannot be tested for simple copies, check edge cases (Subnormal)",
- "bson": "180000001364000100000000000000000000000000000000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1e-6176\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E-6176\"}}"
- },
- {
- "description": "[decq100] underflows cannot be tested for simple copies, check edge cases (Subnormal)",
- "bson": "18000000136400FFFFFFFF095BC138938D44C64D31000000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"999999999999999999999999999999999e-6176\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"9.99999999999999999999999999999999E-6144\"}}"
- },
- {
- "description": "[decq130] fold-downs (more below) (Clamped)",
- "bson": "18000000136400000000807F1BCF85B27059C8A43CFEDF00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-1.23E+6144\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-1.230000000000000000000000000000000E+6144\"}}"
- },
- {
- "description": "[decq132] fold-downs (more below) (Clamped)",
- "bson": "18000000136400000000000A5BC138938D44C64D31FEDF00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-1E+6144\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-1.000000000000000000000000000000000E+6144\"}}"
- },
- {
- "description": "[decq177] Nmin and below (Subnormal)",
- "bson": "180000001364000000000081EFAC855B416D2DEE04008000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.100000000000000000000000000000000E-6143\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-1.00000000000000000000000000000000E-6144\"}}"
- },
- {
- "description": "[decq178] Nmin and below (Subnormal)",
- "bson": "180000001364000000000081EFAC855B416D2DEE04008000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-1.00000000000000000000000000000000E-6144\"}}"
- },
- {
- "description": "[decq179] Nmin and below (Subnormal)",
- "bson": "180000001364000A00000000000000000000000000008000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.000000000000000000000000000000010E-6143\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-1.0E-6175\"}}"
- },
- {
- "description": "[decq180] Nmin and below (Subnormal)",
- "bson": "180000001364000A00000000000000000000000000008000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-1.0E-6175\"}}"
- },
- {
- "description": "[decq181] Nmin and below (Subnormal)",
- "bson": "180000001364000100000000000000000000000000028000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.00000000000000000000000000000001E-6143\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-1E-6175\"}}"
- },
- {
- "description": "[decq182] Nmin and below (Subnormal)",
- "bson": "180000001364000100000000000000000000000000028000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-1E-6175\"}}"
- },
- {
- "description": "[decq183] Nmin and below (Subnormal)",
- "bson": "180000001364000100000000000000000000000000008000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.000000000000000000000000000000001E-6143\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-1E-6176\"}}"
- },
- {
- "description": "[decq184] Nmin and below (Subnormal)",
- "bson": "180000001364000100000000000000000000000000008000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-1E-6176\"}}"
- },
- {
- "description": "[decq190] underflow edge cases (Subnormal)",
- "bson": "180000001364000100000000000000000000000000008000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-1e-6176\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-1E-6176\"}}"
- },
- {
- "description": "[decq200] underflow edge cases (Subnormal)",
- "bson": "18000000136400FFFFFFFF095BC138938D44C64D31008000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-999999999999999999999999999999999e-6176\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-9.99999999999999999999999999999999E-6144\"}}"
- },
- {
- "description": "[decq400] zeros (Clamped)",
- "bson": "180000001364000000000000000000000000000000000000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-8000\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-6176\"}}"
- },
- {
- "description": "[decq401] zeros (Clamped)",
- "bson": "180000001364000000000000000000000000000000000000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-6177\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-6176\"}}"
- },
- {
- "description": "[decq414] clamped zeros... (Clamped)",
- "bson": "180000001364000000000000000000000000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+6112\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+6111\"}}"
- },
- {
- "description": "[decq416] clamped zeros... (Clamped)",
- "bson": "180000001364000000000000000000000000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+6144\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+6111\"}}"
- },
- {
- "description": "[decq418] clamped zeros... (Clamped)",
- "bson": "180000001364000000000000000000000000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+8000\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+6111\"}}"
- },
- {
- "description": "[decq420] negative zeros (Clamped)",
- "bson": "180000001364000000000000000000000000000000008000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E-8000\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E-6176\"}}"
- },
- {
- "description": "[decq421] negative zeros (Clamped)",
- "bson": "180000001364000000000000000000000000000000008000",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E-6177\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E-6176\"}}"
- },
- {
- "description": "[decq434] clamped zeros... (Clamped)",
- "bson": "180000001364000000000000000000000000000000FEDF00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E+6112\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E+6111\"}}"
- },
- {
- "description": "[decq436] clamped zeros... (Clamped)",
- "bson": "180000001364000000000000000000000000000000FEDF00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E+6144\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E+6111\"}}"
- },
- {
- "description": "[decq438] clamped zeros... (Clamped)",
- "bson": "180000001364000000000000000000000000000000FEDF00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E+8000\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E+6111\"}}"
- },
- {
- "description": "[decq601] fold-down full sequence (Clamped)",
- "bson": "18000000136400000000000A5BC138938D44C64D31FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6144\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000000000000000000000000E+6144\"}}"
- },
- {
- "description": "[decq603] fold-down full sequence (Clamped)",
- "bson": "180000001364000000000081EFAC855B416D2DEE04FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6143\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000000000000000000000000000000E+6143\"}}"
- },
- {
- "description": "[decq605] fold-down full sequence (Clamped)",
- "bson": "1800000013640000000080264B91C02220BE377E00FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6142\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0000000000000000000000000000000E+6142\"}}"
- },
- {
- "description": "[decq607] fold-down full sequence (Clamped)",
- "bson": "1800000013640000000040EAED7446D09C2C9F0C00FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6141\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000000000000000000000E+6141\"}}"
- },
- {
- "description": "[decq609] fold-down full sequence (Clamped)",
- "bson": "18000000136400000000A0CA17726DAE0F1E430100FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6140\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000000000000000000000000000E+6140\"}}"
- },
- {
- "description": "[decq611] fold-down full sequence (Clamped)",
- "bson": "18000000136400000000106102253E5ECE4F200000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6139\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0000000000000000000000000000E+6139\"}}"
- },
- {
- "description": "[decq613] fold-down full sequence (Clamped)",
- "bson": "18000000136400000000E83C80D09F3C2E3B030000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6138\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000000000000000000E+6138\"}}"
- },
- {
- "description": "[decq615] fold-down full sequence (Clamped)",
- "bson": "18000000136400000000E4D20CC8DCD2B752000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6137\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000000000000000000000000E+6137\"}}"
- },
- {
- "description": "[decq617] fold-down full sequence (Clamped)",
- "bson": "180000001364000000004A48011416954508000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6136\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0000000000000000000000000E+6136\"}}"
- },
- {
- "description": "[decq619] fold-down full sequence (Clamped)",
- "bson": "18000000136400000000A1EDCCCE1BC2D300000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6135\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000000000000000E+6135\"}}"
- },
- {
- "description": "[decq621] fold-down full sequence (Clamped)",
- "bson": "18000000136400000080F64AE1C7022D1500000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6134\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000000000000000000000E+6134\"}}"
- },
- {
- "description": "[decq623] fold-down full sequence (Clamped)",
- "bson": "18000000136400000040B2BAC9E0191E0200000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6133\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0000000000000000000000E+6133\"}}"
- },
- {
- "description": "[decq625] fold-down full sequence (Clamped)",
- "bson": "180000001364000000A0DEC5ADC935360000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6132\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000000000000E+6132\"}}"
- },
- {
- "description": "[decq627] fold-down full sequence (Clamped)",
- "bson": "18000000136400000010632D5EC76B050000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6131\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000000000000000000E+6131\"}}"
- },
- {
- "description": "[decq629] fold-down full sequence (Clamped)",
- "bson": "180000001364000000E8890423C78A000000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6130\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0000000000000000000E+6130\"}}"
- },
- {
- "description": "[decq631] fold-down full sequence (Clamped)",
- "bson": "18000000136400000064A7B3B6E00D000000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6129\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000000000E+6129\"}}"
- },
- {
- "description": "[decq633] fold-down full sequence (Clamped)",
- "bson": "1800000013640000008A5D78456301000000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6128\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000000000000000E+6128\"}}"
- },
- {
- "description": "[decq635] fold-down full sequence (Clamped)",
- "bson": "180000001364000000C16FF2862300000000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6127\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0000000000000000E+6127\"}}"
- },
- {
- "description": "[decq637] fold-down full sequence (Clamped)",
- "bson": "180000001364000080C6A47E8D0300000000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6126\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000000E+6126\"}}"
- },
- {
- "description": "[decq639] fold-down full sequence (Clamped)",
- "bson": "1800000013640000407A10F35A0000000000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6125\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000000000000E+6125\"}}"
- },
- {
- "description": "[decq641] fold-down full sequence (Clamped)",
- "bson": "1800000013640000A0724E18090000000000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6124\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0000000000000E+6124\"}}"
- },
- {
- "description": "[decq643] fold-down full sequence (Clamped)",
- "bson": "180000001364000010A5D4E8000000000000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6123\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000E+6123\"}}"
- },
- {
- "description": "[decq645] fold-down full sequence (Clamped)",
- "bson": "1800000013640000E8764817000000000000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6122\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000000000E+6122\"}}"
- },
- {
- "description": "[decq647] fold-down full sequence (Clamped)",
- "bson": "1800000013640000E40B5402000000000000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6121\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0000000000E+6121\"}}"
- },
- {
- "description": "[decq649] fold-down full sequence (Clamped)",
- "bson": "1800000013640000CA9A3B00000000000000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6120\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000E+6120\"}}"
- },
- {
- "description": "[decq651] fold-down full sequence (Clamped)",
- "bson": "1800000013640000E1F50500000000000000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6119\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000000E+6119\"}}"
- },
- {
- "description": "[decq653] fold-down full sequence (Clamped)",
- "bson": "180000001364008096980000000000000000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6118\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0000000E+6118\"}}"
- },
- {
- "description": "[decq655] fold-down full sequence (Clamped)",
- "bson": "1800000013640040420F0000000000000000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6117\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000E+6117\"}}"
- },
- {
- "description": "[decq657] fold-down full sequence (Clamped)",
- "bson": "18000000136400A086010000000000000000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6116\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000E+6116\"}}"
- },
- {
- "description": "[decq659] fold-down full sequence (Clamped)",
- "bson": "180000001364001027000000000000000000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6115\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0000E+6115\"}}"
- },
- {
- "description": "[decq661] fold-down full sequence (Clamped)",
- "bson": "18000000136400E803000000000000000000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6114\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000E+6114\"}}"
- },
- {
- "description": "[decq663] fold-down full sequence (Clamped)",
- "bson": "180000001364006400000000000000000000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6113\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00E+6113\"}}"
- },
- {
- "description": "[decq665] fold-down full sequence (Clamped)",
- "bson": "180000001364000A00000000000000000000000000FE5F00",
- "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6112\"}}",
- "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E+6112\"}}"
- }
- ]
-}
-`},
-
- {"decimal128-6.json", `
-{
- "description": "Decimal128",
- "bson_type": "0x13",
- "test_key": "d",
- "parseErrors": [
- {
- "description": "Incomplete Exponent",
- "string": "1e"
- },
- {
- "description": "Exponent at the beginning",
- "string": "E01"
- },
- {
- "description": "Just a decimal place",
- "string": "."
- },
- {
- "description": "2 decimal places",
- "string": "..3"
- },
- {
- "description": "2 decimal places",
- "string": ".13.3"
- },
- {
- "description": "2 decimal places",
- "string": "1..3"
- },
- {
- "description": "2 decimal places",
- "string": "1.3.4"
- },
- {
- "description": "2 decimal places",
- "string": "1.34."
- },
- {
- "description": "Decimal with no digits",
- "string": ".e"
- },
- {
- "description": "2 signs",
- "string": "+-32.4"
- },
- {
- "description": "2 signs",
- "string": "-+32.4"
- },
- {
- "description": "2 negative signs",
- "string": "--32.4"
- },
- {
- "description": "2 negative signs",
- "string": "-32.-4"
- },
- {
- "description": "End in negative sign",
- "string": "32.0-"
- },
- {
- "description": "2 negative signs",
- "string": "32.4E--21"
- },
- {
- "description": "2 negative signs",
- "string": "32.4E-2-1"
- },
- {
- "description": "2 signs",
- "string": "32.4E+-21"
- },
- {
- "description": "Empty string",
- "string": ""
- },
- {
- "description": "leading white space positive number",
- "string": " 1"
- },
- {
- "description": "leading white space negative number",
- "string": " -1"
- },
- {
- "description": "trailing white space",
- "string": "1 "
- },
- {
- "description": "Invalid",
- "string": "E"
- },
- {
- "description": "Invalid",
- "string": "invalid"
- },
- {
- "description": "Invalid",
- "string": "i"
- },
- {
- "description": "Invalid",
- "string": "in"
- },
- {
- "description": "Invalid",
- "string": "-in"
- },
- {
- "description": "Invalid",
- "string": "Na"
- },
- {
- "description": "Invalid",
- "string": "-Na"
- },
- {
- "description": "Invalid",
- "string": "1.23abc"
- },
- {
- "description": "Invalid",
- "string": "1.23abcE+02"
- },
- {
- "description": "Invalid",
- "string": "1.23E+0aabs2"
- }
- ]
-}
-`},
-
- {"decimal128-7.json", `
-{
- "description": "Decimal128",
- "bson_type": "0x13",
- "test_key": "d",
- "parseErrors": [
- {
- "description": "[basx572] Near-specials (Conversion_syntax)",
- "string": "-9Inf"
- },
- {
- "description": "[basx516] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "-1-"
- },
- {
- "description": "[basx533] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "0000.."
- },
- {
- "description": "[basx534] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": ".0000."
- },
- {
- "description": "[basx535] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "00..00"
- },
- {
- "description": "[basx569] Near-specials (Conversion_syntax)",
- "string": "0Inf"
- },
- {
- "description": "[basx571] Near-specials (Conversion_syntax)",
- "string": "-0Inf"
- },
- {
- "description": "[basx575] Near-specials (Conversion_syntax)",
- "string": "0sNaN"
- },
- {
- "description": "[basx503] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "++1"
- },
- {
- "description": "[basx504] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "--1"
- },
- {
- "description": "[basx505] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "-+1"
- },
- {
- "description": "[basx506] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "+-1"
- },
- {
- "description": "[basx510] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": " +1"
- },
- {
- "description": "[basx513] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": " + 1"
- },
- {
- "description": "[basx514] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": " - 1"
- },
- {
- "description": "[basx501] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "."
- },
- {
- "description": "[basx502] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": ".."
- },
- {
- "description": "[basx519] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": ""
- },
- {
- "description": "[basx525] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "e100"
- },
- {
- "description": "[basx549] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "e+1"
- },
- {
- "description": "[basx577] some baddies with dots and Es and dots and specials (Conversion_syntax)",
- "string": ".e+1"
- },
- {
- "description": "[basx578] some baddies with dots and Es and dots and specials (Conversion_syntax)",
- "string": "+.e+1"
- },
- {
- "description": "[basx581] some baddies with dots and Es and dots and specials (Conversion_syntax)",
- "string": "E+1"
- },
- {
- "description": "[basx582] some baddies with dots and Es and dots and specials (Conversion_syntax)",
- "string": ".E+1"
- },
- {
- "description": "[basx583] some baddies with dots and Es and dots and specials (Conversion_syntax)",
- "string": "+.E+1"
- },
- {
- "description": "[basx579] some baddies with dots and Es and dots and specials (Conversion_syntax)",
- "string": "-.e+"
- },
- {
- "description": "[basx580] some baddies with dots and Es and dots and specials (Conversion_syntax)",
- "string": "-.e"
- },
- {
- "description": "[basx584] some baddies with dots and Es and dots and specials (Conversion_syntax)",
- "string": "-.E+"
- },
- {
- "description": "[basx585] some baddies with dots and Es and dots and specials (Conversion_syntax)",
- "string": "-.E"
- },
- {
- "description": "[basx589] some baddies with dots and Es and dots and specials (Conversion_syntax)",
- "string": "+.Inf"
- },
- {
- "description": "[basx586] some baddies with dots and Es and dots and specials (Conversion_syntax)",
- "string": ".NaN"
- },
- {
- "description": "[basx587] some baddies with dots and Es and dots and specials (Conversion_syntax)",
- "string": "-.NaN"
- },
- {
- "description": "[basx545] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "ONE"
- },
- {
- "description": "[basx561] Near-specials (Conversion_syntax)",
- "string": "qNaN"
- },
- {
- "description": "[basx573] Near-specials (Conversion_syntax)",
- "string": "-sNa"
- },
- {
- "description": "[basx588] some baddies with dots and Es and dots and specials (Conversion_syntax)",
- "string": "+.sNaN"
- },
- {
- "description": "[basx544] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "ten"
- },
- {
- "description": "[basx527] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "u0b65"
- },
- {
- "description": "[basx526] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "u0e5a"
- },
- {
- "description": "[basx515] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "x"
- },
- {
- "description": "[basx574] Near-specials (Conversion_syntax)",
- "string": "xNaN"
- },
- {
- "description": "[basx530] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": ".123.5"
- },
- {
- "description": "[basx500] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "1..2"
- },
- {
- "description": "[basx542] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "1e1.0"
- },
- {
- "description": "[basx553] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "1E+1.2.3"
- },
- {
- "description": "[basx543] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "1e123e"
- },
- {
- "description": "[basx552] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "1E+1.2"
- },
- {
- "description": "[basx546] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "1e.1"
- },
- {
- "description": "[basx547] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "1e1."
- },
- {
- "description": "[basx554] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "1E++1"
- },
- {
- "description": "[basx555] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "1E--1"
- },
- {
- "description": "[basx556] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "1E+-1"
- },
- {
- "description": "[basx557] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "1E-+1"
- },
- {
- "description": "[basx558] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "1E'1"
- },
- {
- "description": "[basx559] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "1E\"1"
- },
- {
- "description": "[basx520] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "1e-"
- },
- {
- "description": "[basx560] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "1E"
- },
- {
- "description": "[basx548] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "1ee"
- },
- {
- "description": "[basx551] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "1.2.1"
- },
- {
- "description": "[basx550] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "1.23.4"
- },
- {
- "description": "[basx529] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "1.34.5"
- },
- {
- "description": "[basx531] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "01.35."
- },
- {
- "description": "[basx532] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "01.35-"
- },
- {
- "description": "[basx518] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "3+"
- },
- {
- "description": "[basx521] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "7e99999a"
- },
- {
- "description": "[basx570] Near-specials (Conversion_syntax)",
- "string": "9Inf"
- },
- {
- "description": "[basx512] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "12 "
- },
- {
- "description": "[basx517] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "12-"
- },
- {
- "description": "[basx507] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "12e"
- },
- {
- "description": "[basx508] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "12e++"
- },
- {
- "description": "[basx509] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "12f4"
- },
- {
- "description": "[basx536] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "111e*123"
- },
- {
- "description": "[basx537] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "111e123-"
- },
- {
- "description": "[basx540] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "111e1*23"
- },
- {
- "description": "[basx538] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "111e+12+"
- },
- {
- "description": "[basx539] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "111e1-3-"
- },
- {
- "description": "[basx541] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "111E1e+3"
- },
- {
- "description": "[basx528] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "123,65"
- },
- {
- "description": "[basx523] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "7e12356789012x"
- },
- {
- "description": "[basx522] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
- "string": "7e123567890x"
- }
- ]
-}
-`},
-}
diff --git a/vendor/gopkg.in.o/mgo.v2/bson/decode.go b/vendor/gopkg.in.o/mgo.v2/bson/decode.go
deleted file mode 100644
index 7c2d8416a..000000000
--- a/vendor/gopkg.in.o/mgo.v2/bson/decode.go
+++ /dev/null
@@ -1,849 +0,0 @@
-// BSON library for Go
-//
-// Copyright (c) 2010-2012 - Gustavo Niemeyer
-//
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// gobson - BSON library for Go.
-
-package bson
-
-import (
- "fmt"
- "math"
- "net/url"
- "reflect"
- "strconv"
- "sync"
- "time"
-)
-
-type decoder struct {
- in []byte
- i int
- docType reflect.Type
-}
-
-var typeM = reflect.TypeOf(M{})
-
-func newDecoder(in []byte) *decoder {
- return &decoder{in, 0, typeM}
-}
-
-// --------------------------------------------------------------------------
-// Some helper functions.
-
-func corrupted() {
- panic("Document is corrupted")
-}
-
-func settableValueOf(i interface{}) reflect.Value {
- v := reflect.ValueOf(i)
- sv := reflect.New(v.Type()).Elem()
- sv.Set(v)
- return sv
-}
-
-// --------------------------------------------------------------------------
-// Unmarshaling of documents.
-
-const (
- setterUnknown = iota
- setterNone
- setterType
- setterAddr
-)
-
-var setterStyles map[reflect.Type]int
-var setterIface reflect.Type
-var setterMutex sync.RWMutex
-
-func init() {
- var iface Setter
- setterIface = reflect.TypeOf(&iface).Elem()
- setterStyles = make(map[reflect.Type]int)
-}
-
-func setterStyle(outt reflect.Type) int {
- setterMutex.RLock()
- style := setterStyles[outt]
- setterMutex.RUnlock()
- if style == setterUnknown {
- setterMutex.Lock()
- defer setterMutex.Unlock()
- if outt.Implements(setterIface) {
- setterStyles[outt] = setterType
- } else if reflect.PtrTo(outt).Implements(setterIface) {
- setterStyles[outt] = setterAddr
- } else {
- setterStyles[outt] = setterNone
- }
- style = setterStyles[outt]
- }
- return style
-}
-
-func getSetter(outt reflect.Type, out reflect.Value) Setter {
- style := setterStyle(outt)
- if style == setterNone {
- return nil
- }
- if style == setterAddr {
- if !out.CanAddr() {
- return nil
- }
- out = out.Addr()
- } else if outt.Kind() == reflect.Ptr && out.IsNil() {
- out.Set(reflect.New(outt.Elem()))
- }
- return out.Interface().(Setter)
-}
-
-func clearMap(m reflect.Value) {
- var none reflect.Value
- for _, k := range m.MapKeys() {
- m.SetMapIndex(k, none)
- }
-}
-
-func (d *decoder) readDocTo(out reflect.Value) {
- var elemType reflect.Type
- outt := out.Type()
- outk := outt.Kind()
-
- for {
- if outk == reflect.Ptr && out.IsNil() {
- out.Set(reflect.New(outt.Elem()))
- }
- if setter := getSetter(outt, out); setter != nil {
- var raw Raw
- d.readDocTo(reflect.ValueOf(&raw))
- err := setter.SetBSON(raw)
- if _, ok := err.(*TypeError); err != nil && !ok {
- panic(err)
- }
- return
- }
- if outk == reflect.Ptr {
- out = out.Elem()
- outt = out.Type()
- outk = out.Kind()
- continue
- }
- break
- }
-
- var fieldsMap map[string]fieldInfo
- var inlineMap reflect.Value
- start := d.i
-
- origout := out
- if outk == reflect.Interface {
- if d.docType.Kind() == reflect.Map {
- mv := reflect.MakeMap(d.docType)
- out.Set(mv)
- out = mv
- } else {
- dv := reflect.New(d.docType).Elem()
- out.Set(dv)
- out = dv
- }
- outt = out.Type()
- outk = outt.Kind()
- }
-
- docType := d.docType
- keyType := typeString
- convertKey := false
- switch outk {
- case reflect.Map:
- keyType = outt.Key()
- if keyType.Kind() != reflect.String {
- panic("BSON map must have string keys. Got: " + outt.String())
- }
- if keyType != typeString {
- convertKey = true
- }
- elemType = outt.Elem()
- if elemType == typeIface {
- d.docType = outt
- }
- if out.IsNil() {
- out.Set(reflect.MakeMap(out.Type()))
- } else if out.Len() > 0 {
- clearMap(out)
- }
- case reflect.Struct:
- if outt != typeRaw {
- sinfo, err := getStructInfo(out.Type())
- if err != nil {
- panic(err)
- }
- fieldsMap = sinfo.FieldsMap
- out.Set(sinfo.Zero)
- if sinfo.InlineMap != -1 {
- inlineMap = out.Field(sinfo.InlineMap)
- if !inlineMap.IsNil() && inlineMap.Len() > 0 {
- clearMap(inlineMap)
- }
- elemType = inlineMap.Type().Elem()
- if elemType == typeIface {
- d.docType = inlineMap.Type()
- }
- }
- }
- case reflect.Slice:
- switch outt.Elem() {
- case typeDocElem:
- origout.Set(d.readDocElems(outt))
- return
- case typeRawDocElem:
- origout.Set(d.readRawDocElems(outt))
- return
- }
- fallthrough
- default:
- panic("Unsupported document type for unmarshalling: " + out.Type().String())
- }
-
- end := int(d.readInt32())
- end += d.i - 4
- if end <= d.i || end > len(d.in) || d.in[end-1] != '\x00' {
- corrupted()
- }
- for d.in[d.i] != '\x00' {
- kind := d.readByte()
- name := d.readCStr()
- if d.i >= end {
- corrupted()
- }
-
- switch outk {
- case reflect.Map:
- e := reflect.New(elemType).Elem()
- if d.readElemTo(e, kind) {
- k := reflect.ValueOf(name)
- if convertKey {
- k = k.Convert(keyType)
- }
- out.SetMapIndex(k, e)
- }
- case reflect.Struct:
- if outt == typeRaw {
- d.dropElem(kind)
- } else {
- if info, ok := fieldsMap[name]; ok {
- if info.Inline == nil {
- d.readElemTo(out.Field(info.Num), kind)
- } else {
- d.readElemTo(out.FieldByIndex(info.Inline), kind)
- }
- } else if inlineMap.IsValid() {
- if inlineMap.IsNil() {
- inlineMap.Set(reflect.MakeMap(inlineMap.Type()))
- }
- e := reflect.New(elemType).Elem()
- if d.readElemTo(e, kind) {
- inlineMap.SetMapIndex(reflect.ValueOf(name), e)
- }
- } else {
- d.dropElem(kind)
- }
- }
- case reflect.Slice:
- }
-
- if d.i >= end {
- corrupted()
- }
- }
- d.i++ // '\x00'
- if d.i != end {
- corrupted()
- }
- d.docType = docType
-
- if outt == typeRaw {
- out.Set(reflect.ValueOf(Raw{0x03, d.in[start:d.i]}))
- }
-}
-
-func (d *decoder) readArrayDocTo(out reflect.Value) {
- end := int(d.readInt32())
- end += d.i - 4
- if end <= d.i || end > len(d.in) || d.in[end-1] != '\x00' {
- corrupted()
- }
- i := 0
- l := out.Len()
- for d.in[d.i] != '\x00' {
- if i >= l {
- panic("Length mismatch on array field")
- }
- kind := d.readByte()
- for d.i < end && d.in[d.i] != '\x00' {
- d.i++
- }
- if d.i >= end {
- corrupted()
- }
- d.i++
- d.readElemTo(out.Index(i), kind)
- if d.i >= end {
- corrupted()
- }
- i++
- }
- if i != l {
- panic("Length mismatch on array field")
- }
- d.i++ // '\x00'
- if d.i != end {
- corrupted()
- }
-}
-
-func (d *decoder) readSliceDoc(t reflect.Type) interface{} {
- tmp := make([]reflect.Value, 0, 8)
- elemType := t.Elem()
- if elemType == typeRawDocElem {
- d.dropElem(0x04)
- return reflect.Zero(t).Interface()
- }
-
- end := int(d.readInt32())
- end += d.i - 4
- if end <= d.i || end > len(d.in) || d.in[end-1] != '\x00' {
- corrupted()
- }
- for d.in[d.i] != '\x00' {
- kind := d.readByte()
- for d.i < end && d.in[d.i] != '\x00' {
- d.i++
- }
- if d.i >= end {
- corrupted()
- }
- d.i++
- e := reflect.New(elemType).Elem()
- if d.readElemTo(e, kind) {
- tmp = append(tmp, e)
- }
- if d.i >= end {
- corrupted()
- }
- }
- d.i++ // '\x00'
- if d.i != end {
- corrupted()
- }
-
- n := len(tmp)
- slice := reflect.MakeSlice(t, n, n)
- for i := 0; i != n; i++ {
- slice.Index(i).Set(tmp[i])
- }
- return slice.Interface()
-}
-
-var typeSlice = reflect.TypeOf([]interface{}{})
-var typeIface = typeSlice.Elem()
-
-func (d *decoder) readDocElems(typ reflect.Type) reflect.Value {
- docType := d.docType
- d.docType = typ
- slice := make([]DocElem, 0, 8)
- d.readDocWith(func(kind byte, name string) {
- e := DocElem{Name: name}
- v := reflect.ValueOf(&e.Value)
- if d.readElemTo(v.Elem(), kind) {
- slice = append(slice, e)
- }
- })
- slicev := reflect.New(typ).Elem()
- slicev.Set(reflect.ValueOf(slice))
- d.docType = docType
- return slicev
-}
-
-func (d *decoder) readRawDocElems(typ reflect.Type) reflect.Value {
- docType := d.docType
- d.docType = typ
- slice := make([]RawDocElem, 0, 8)
- d.readDocWith(func(kind byte, name string) {
- e := RawDocElem{Name: name}
- v := reflect.ValueOf(&e.Value)
- if d.readElemTo(v.Elem(), kind) {
- slice = append(slice, e)
- }
- })
- slicev := reflect.New(typ).Elem()
- slicev.Set(reflect.ValueOf(slice))
- d.docType = docType
- return slicev
-}
-
-func (d *decoder) readDocWith(f func(kind byte, name string)) {
- end := int(d.readInt32())
- end += d.i - 4
- if end <= d.i || end > len(d.in) || d.in[end-1] != '\x00' {
- corrupted()
- }
- for d.in[d.i] != '\x00' {
- kind := d.readByte()
- name := d.readCStr()
- if d.i >= end {
- corrupted()
- }
- f(kind, name)
- if d.i >= end {
- corrupted()
- }
- }
- d.i++ // '\x00'
- if d.i != end {
- corrupted()
- }
-}
-
-// --------------------------------------------------------------------------
-// Unmarshaling of individual elements within a document.
-
-var blackHole = settableValueOf(struct{}{})
-
-func (d *decoder) dropElem(kind byte) {
- d.readElemTo(blackHole, kind)
-}
-
-// Attempt to decode an element from the document and put it into out.
-// If the types are not compatible, the returned ok value will be
-// false and out will be unchanged.
-func (d *decoder) readElemTo(out reflect.Value, kind byte) (good bool) {
-
- start := d.i
-
- if kind == 0x03 {
- // Delegate unmarshaling of documents.
- outt := out.Type()
- outk := out.Kind()
- switch outk {
- case reflect.Interface, reflect.Ptr, reflect.Struct, reflect.Map:
- d.readDocTo(out)
- return true
- }
- if setterStyle(outt) != setterNone {
- d.readDocTo(out)
- return true
- }
- if outk == reflect.Slice {
- switch outt.Elem() {
- case typeDocElem:
- out.Set(d.readDocElems(outt))
- case typeRawDocElem:
- out.Set(d.readRawDocElems(outt))
- default:
- d.readDocTo(blackHole)
- }
- return true
- }
- d.readDocTo(blackHole)
- return true
- }
-
- var in interface{}
-
- switch kind {
- case 0x01: // Float64
- in = d.readFloat64()
- case 0x02: // UTF-8 string
- in = d.readStr()
- case 0x03: // Document
- panic("Can't happen. Handled above.")
- case 0x04: // Array
- outt := out.Type()
- if setterStyle(outt) != setterNone {
- // Skip the value so its data is handed to the setter below.
- d.dropElem(kind)
- break
- }
- for outt.Kind() == reflect.Ptr {
- outt = outt.Elem()
- }
- switch outt.Kind() {
- case reflect.Array:
- d.readArrayDocTo(out)
- return true
- case reflect.Slice:
- in = d.readSliceDoc(outt)
- default:
- in = d.readSliceDoc(typeSlice)
- }
- case 0x05: // Binary
- b := d.readBinary()
- if b.Kind == 0x00 || b.Kind == 0x02 {
- in = b.Data
- } else {
- in = b
- }
- case 0x06: // Undefined (obsolete, but still seen in the wild)
- in = Undefined
- case 0x07: // ObjectId
- in = ObjectId(d.readBytes(12))
- case 0x08: // Bool
- in = d.readBool()
- case 0x09: // Timestamp
- // MongoDB handles timestamps as milliseconds.
- i := d.readInt64()
- if i == -62135596800000 {
- in = time.Time{} // In UTC for convenience.
- } else {
- in = time.Unix(i/1e3, i%1e3*1e6)
- }
- case 0x0A: // Nil
- in = nil
- case 0x0B: // RegEx
- in = d.readRegEx()
- case 0x0C:
- in = DBPointer{Namespace: d.readStr(), Id: ObjectId(d.readBytes(12))}
- case 0x0D: // JavaScript without scope
- in = JavaScript{Code: d.readStr()}
- case 0x0E: // Symbol
- in = Symbol(d.readStr())
- case 0x0F: // JavaScript with scope
- d.i += 4 // Skip length
- js := JavaScript{d.readStr(), make(M)}
- d.readDocTo(reflect.ValueOf(js.Scope))
- in = js
- case 0x10: // Int32
- in = int(d.readInt32())
- case 0x11: // Mongo-specific timestamp
- in = MongoTimestamp(d.readInt64())
- case 0x12: // Int64
- in = d.readInt64()
- case 0x13: // Decimal128
- in = Decimal128{
- l: uint64(d.readInt64()),
- h: uint64(d.readInt64()),
- }
- case 0x7F: // Max key
- in = MaxKey
- case 0xFF: // Min key
- in = MinKey
- default:
- panic(fmt.Sprintf("Unknown element kind (0x%02X)", kind))
- }
-
- outt := out.Type()
-
- if outt == typeRaw {
- out.Set(reflect.ValueOf(Raw{kind, d.in[start:d.i]}))
- return true
- }
-
- if setter := getSetter(outt, out); setter != nil {
- err := setter.SetBSON(Raw{kind, d.in[start:d.i]})
- if err == SetZero {
- out.Set(reflect.Zero(outt))
- return true
- }
- if err == nil {
- return true
- }
- if _, ok := err.(*TypeError); !ok {
- panic(err)
- }
- return false
- }
-
- if in == nil {
- out.Set(reflect.Zero(outt))
- return true
- }
-
- outk := outt.Kind()
-
- // Dereference and initialize pointer if necessary.
- first := true
- for outk == reflect.Ptr {
- if !out.IsNil() {
- out = out.Elem()
- } else {
- elem := reflect.New(outt.Elem())
- if first {
- // Only set if value is compatible.
- first = false
- defer func(out, elem reflect.Value) {
- if good {
- out.Set(elem)
- }
- }(out, elem)
- } else {
- out.Set(elem)
- }
- out = elem
- }
- outt = out.Type()
- outk = outt.Kind()
- }
-
- inv := reflect.ValueOf(in)
- if outt == inv.Type() {
- out.Set(inv)
- return true
- }
-
- switch outk {
- case reflect.Interface:
- out.Set(inv)
- return true
- case reflect.String:
- switch inv.Kind() {
- case reflect.String:
- out.SetString(inv.String())
- return true
- case reflect.Slice:
- if b, ok := in.([]byte); ok {
- out.SetString(string(b))
- return true
- }
- case reflect.Int, reflect.Int64:
- if outt == typeJSONNumber {
- out.SetString(strconv.FormatInt(inv.Int(), 10))
- return true
- }
- case reflect.Float64:
- if outt == typeJSONNumber {
- out.SetString(strconv.FormatFloat(inv.Float(), 'f', -1, 64))
- return true
- }
- }
- case reflect.Slice, reflect.Array:
- // Remember, array (0x04) slices are built with the correct
- // element type. If we are here, must be a cross BSON kind
- // conversion (e.g. 0x05 unmarshalling on string).
- if outt.Elem().Kind() != reflect.Uint8 {
- break
- }
- switch inv.Kind() {
- case reflect.String:
- slice := []byte(inv.String())
- out.Set(reflect.ValueOf(slice))
- return true
- case reflect.Slice:
- switch outt.Kind() {
- case reflect.Array:
- reflect.Copy(out, inv)
- case reflect.Slice:
- out.SetBytes(inv.Bytes())
- }
- return true
- }
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- switch inv.Kind() {
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- out.SetInt(inv.Int())
- return true
- case reflect.Float32, reflect.Float64:
- out.SetInt(int64(inv.Float()))
- return true
- case reflect.Bool:
- if inv.Bool() {
- out.SetInt(1)
- } else {
- out.SetInt(0)
- }
- return true
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
- panic("can't happen: no uint types in BSON (!?)")
- }
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
- switch inv.Kind() {
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- out.SetUint(uint64(inv.Int()))
- return true
- case reflect.Float32, reflect.Float64:
- out.SetUint(uint64(inv.Float()))
- return true
- case reflect.Bool:
- if inv.Bool() {
- out.SetUint(1)
- } else {
- out.SetUint(0)
- }
- return true
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
- panic("Can't happen. No uint types in BSON.")
- }
- case reflect.Float32, reflect.Float64:
- switch inv.Kind() {
- case reflect.Float32, reflect.Float64:
- out.SetFloat(inv.Float())
- return true
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- out.SetFloat(float64(inv.Int()))
- return true
- case reflect.Bool:
- if inv.Bool() {
- out.SetFloat(1)
- } else {
- out.SetFloat(0)
- }
- return true
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
- panic("Can't happen. No uint types in BSON?")
- }
- case reflect.Bool:
- switch inv.Kind() {
- case reflect.Bool:
- out.SetBool(inv.Bool())
- return true
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- out.SetBool(inv.Int() != 0)
- return true
- case reflect.Float32, reflect.Float64:
- out.SetBool(inv.Float() != 0)
- return true
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
- panic("Can't happen. No uint types in BSON?")
- }
- case reflect.Struct:
- if outt == typeURL && inv.Kind() == reflect.String {
- u, err := url.Parse(inv.String())
- if err != nil {
- panic(err)
- }
- out.Set(reflect.ValueOf(u).Elem())
- return true
- }
- if outt == typeBinary {
- if b, ok := in.([]byte); ok {
- out.Set(reflect.ValueOf(Binary{Data: b}))
- return true
- }
- }
- }
-
- return false
-}
-
-// --------------------------------------------------------------------------
-// Parsers of basic types.
-
-func (d *decoder) readRegEx() RegEx {
- re := RegEx{}
- re.Pattern = d.readCStr()
- re.Options = d.readCStr()
- return re
-}
-
-func (d *decoder) readBinary() Binary {
- l := d.readInt32()
- b := Binary{}
- b.Kind = d.readByte()
- b.Data = d.readBytes(l)
- if b.Kind == 0x02 && len(b.Data) >= 4 {
- // Weird obsolete format with redundant length.
- b.Data = b.Data[4:]
- }
- return b
-}
-
-func (d *decoder) readStr() string {
- l := d.readInt32()
- b := d.readBytes(l - 1)
- if d.readByte() != '\x00' {
- corrupted()
- }
- return string(b)
-}
-
-func (d *decoder) readCStr() string {
- start := d.i
- end := start
- l := len(d.in)
- for ; end != l; end++ {
- if d.in[end] == '\x00' {
- break
- }
- }
- d.i = end + 1
- if d.i > l {
- corrupted()
- }
- return string(d.in[start:end])
-}
-
-func (d *decoder) readBool() bool {
- b := d.readByte()
- if b == 0 {
- return false
- }
- if b == 1 {
- return true
- }
- panic(fmt.Sprintf("encoded boolean must be 1 or 0, found %d", b))
-}
-
-func (d *decoder) readFloat64() float64 {
- return math.Float64frombits(uint64(d.readInt64()))
-}
-
-func (d *decoder) readInt32() int32 {
- b := d.readBytes(4)
- return int32((uint32(b[0]) << 0) |
- (uint32(b[1]) << 8) |
- (uint32(b[2]) << 16) |
- (uint32(b[3]) << 24))
-}
-
-func (d *decoder) readInt64() int64 {
- b := d.readBytes(8)
- return int64((uint64(b[0]) << 0) |
- (uint64(b[1]) << 8) |
- (uint64(b[2]) << 16) |
- (uint64(b[3]) << 24) |
- (uint64(b[4]) << 32) |
- (uint64(b[5]) << 40) |
- (uint64(b[6]) << 48) |
- (uint64(b[7]) << 56))
-}
-
-func (d *decoder) readByte() byte {
- i := d.i
- d.i++
- if d.i > len(d.in) {
- corrupted()
- }
- return d.in[i]
-}
-
-func (d *decoder) readBytes(length int32) []byte {
- if length < 0 {
- corrupted()
- }
- start := d.i
- d.i += int(length)
- if d.i < start || d.i > len(d.in) {
- corrupted()
- }
- return d.in[start : start+int(length)]
-}
diff --git a/vendor/gopkg.in.o/mgo.v2/bson/encode.go b/vendor/gopkg.in.o/mgo.v2/bson/encode.go
deleted file mode 100644
index add39e865..000000000
--- a/vendor/gopkg.in.o/mgo.v2/bson/encode.go
+++ /dev/null
@@ -1,514 +0,0 @@
-// BSON library for Go
-//
-// Copyright (c) 2010-2012 - Gustavo Niemeyer
-//
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// gobson - BSON library for Go.
-
-package bson
-
-import (
- "encoding/json"
- "fmt"
- "math"
- "net/url"
- "reflect"
- "strconv"
- "time"
-)
-
-// --------------------------------------------------------------------------
-// Some internal infrastructure.
-
-var (
- typeBinary = reflect.TypeOf(Binary{})
- typeObjectId = reflect.TypeOf(ObjectId(""))
- typeDBPointer = reflect.TypeOf(DBPointer{"", ObjectId("")})
- typeSymbol = reflect.TypeOf(Symbol(""))
- typeMongoTimestamp = reflect.TypeOf(MongoTimestamp(0))
- typeOrderKey = reflect.TypeOf(MinKey)
- typeDocElem = reflect.TypeOf(DocElem{})
- typeRawDocElem = reflect.TypeOf(RawDocElem{})
- typeRaw = reflect.TypeOf(Raw{})
- typeURL = reflect.TypeOf(url.URL{})
- typeTime = reflect.TypeOf(time.Time{})
- typeString = reflect.TypeOf("")
- typeJSONNumber = reflect.TypeOf(json.Number(""))
-)
-
-const itoaCacheSize = 32
-
-var itoaCache []string
-
-func init() {
- itoaCache = make([]string, itoaCacheSize)
- for i := 0; i != itoaCacheSize; i++ {
- itoaCache[i] = strconv.Itoa(i)
- }
-}
-
-func itoa(i int) string {
- if i < itoaCacheSize {
- return itoaCache[i]
- }
- return strconv.Itoa(i)
-}
-
-// --------------------------------------------------------------------------
-// Marshaling of the document value itself.
-
-type encoder struct {
- out []byte
-}
-
-func (e *encoder) addDoc(v reflect.Value) {
- for {
- if vi, ok := v.Interface().(Getter); ok {
- getv, err := vi.GetBSON()
- if err != nil {
- panic(err)
- }
- v = reflect.ValueOf(getv)
- continue
- }
- if v.Kind() == reflect.Ptr {
- v = v.Elem()
- continue
- }
- break
- }
-
- if v.Type() == typeRaw {
- raw := v.Interface().(Raw)
- if raw.Kind != 0x03 && raw.Kind != 0x00 {
- panic("Attempted to marshal Raw kind " + strconv.Itoa(int(raw.Kind)) + " as a document")
- }
- if len(raw.Data) == 0 {
- panic("Attempted to marshal empty Raw document")
- }
- e.addBytes(raw.Data...)
- return
- }
-
- start := e.reserveInt32()
-
- switch v.Kind() {
- case reflect.Map:
- e.addMap(v)
- case reflect.Struct:
- e.addStruct(v)
- case reflect.Array, reflect.Slice:
- e.addSlice(v)
- default:
- panic("Can't marshal " + v.Type().String() + " as a BSON document")
- }
-
- e.addBytes(0)
- e.setInt32(start, int32(len(e.out)-start))
-}
-
-func (e *encoder) addMap(v reflect.Value) {
- for _, k := range v.MapKeys() {
- e.addElem(k.String(), v.MapIndex(k), false)
- }
-}
-
-func (e *encoder) addStruct(v reflect.Value) {
- sinfo, err := getStructInfo(v.Type())
- if err != nil {
- panic(err)
- }
- var value reflect.Value
- if sinfo.InlineMap >= 0 {
- m := v.Field(sinfo.InlineMap)
- if m.Len() > 0 {
- for _, k := range m.MapKeys() {
- ks := k.String()
- if _, found := sinfo.FieldsMap[ks]; found {
- panic(fmt.Sprintf("Can't have key %q in inlined map; conflicts with struct field", ks))
- }
- e.addElem(ks, m.MapIndex(k), false)
- }
- }
- }
- for _, info := range sinfo.FieldsList {
- if info.Inline == nil {
- value = v.Field(info.Num)
- } else {
- value = v.FieldByIndex(info.Inline)
- }
- if info.OmitEmpty && isZero(value) {
- continue
- }
- e.addElem(info.Key, value, info.MinSize)
- }
-}
-
-func isZero(v reflect.Value) bool {
- switch v.Kind() {
- case reflect.String:
- return len(v.String()) == 0
- case reflect.Ptr, reflect.Interface:
- return v.IsNil()
- case reflect.Slice:
- return v.Len() == 0
- case reflect.Map:
- return v.Len() == 0
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- return v.Int() == 0
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
- return v.Uint() == 0
- case reflect.Float32, reflect.Float64:
- return v.Float() == 0
- case reflect.Bool:
- return !v.Bool()
- case reflect.Struct:
- vt := v.Type()
- if vt == typeTime {
- return v.Interface().(time.Time).IsZero()
- }
- for i := 0; i < v.NumField(); i++ {
- if vt.Field(i).PkgPath != "" && !vt.Field(i).Anonymous {
- continue // Private field
- }
- if !isZero(v.Field(i)) {
- return false
- }
- }
- return true
- }
- return false
-}
-
-func (e *encoder) addSlice(v reflect.Value) {
- vi := v.Interface()
- if d, ok := vi.(D); ok {
- for _, elem := range d {
- e.addElem(elem.Name, reflect.ValueOf(elem.Value), false)
- }
- return
- }
- if d, ok := vi.(RawD); ok {
- for _, elem := range d {
- e.addElem(elem.Name, reflect.ValueOf(elem.Value), false)
- }
- return
- }
- l := v.Len()
- et := v.Type().Elem()
- if et == typeDocElem {
- for i := 0; i < l; i++ {
- elem := v.Index(i).Interface().(DocElem)
- e.addElem(elem.Name, reflect.ValueOf(elem.Value), false)
- }
- return
- }
- if et == typeRawDocElem {
- for i := 0; i < l; i++ {
- elem := v.Index(i).Interface().(RawDocElem)
- e.addElem(elem.Name, reflect.ValueOf(elem.Value), false)
- }
- return
- }
- for i := 0; i < l; i++ {
- e.addElem(itoa(i), v.Index(i), false)
- }
-}
-
-// --------------------------------------------------------------------------
-// Marshaling of elements in a document.
-
-func (e *encoder) addElemName(kind byte, name string) {
- e.addBytes(kind)
- e.addBytes([]byte(name)...)
- e.addBytes(0)
-}
-
-func (e *encoder) addElem(name string, v reflect.Value, minSize bool) {
-
- if !v.IsValid() {
- e.addElemName(0x0A, name)
- return
- }
-
- if getter, ok := v.Interface().(Getter); ok {
- getv, err := getter.GetBSON()
- if err != nil {
- panic(err)
- }
- e.addElem(name, reflect.ValueOf(getv), minSize)
- return
- }
-
- switch v.Kind() {
-
- case reflect.Interface:
- e.addElem(name, v.Elem(), minSize)
-
- case reflect.Ptr:
- e.addElem(name, v.Elem(), minSize)
-
- case reflect.String:
- s := v.String()
- switch v.Type() {
- case typeObjectId:
- if len(s) != 12 {
- panic("ObjectIDs must be exactly 12 bytes long (got " +
- strconv.Itoa(len(s)) + ")")
- }
- e.addElemName(0x07, name)
- e.addBytes([]byte(s)...)
- case typeSymbol:
- e.addElemName(0x0E, name)
- e.addStr(s)
- case typeJSONNumber:
- n := v.Interface().(json.Number)
- if i, err := n.Int64(); err == nil {
- e.addElemName(0x12, name)
- e.addInt64(i)
- } else if f, err := n.Float64(); err == nil {
- e.addElemName(0x01, name)
- e.addFloat64(f)
- } else {
- panic("failed to convert json.Number to a number: " + s)
- }
- default:
- e.addElemName(0x02, name)
- e.addStr(s)
- }
-
- case reflect.Float32, reflect.Float64:
- e.addElemName(0x01, name)
- e.addFloat64(v.Float())
-
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
- u := v.Uint()
- if int64(u) < 0 {
- panic("BSON has no uint64 type, and value is too large to fit correctly in an int64")
- } else if u <= math.MaxInt32 && (minSize || v.Kind() <= reflect.Uint32) {
- e.addElemName(0x10, name)
- e.addInt32(int32(u))
- } else {
- e.addElemName(0x12, name)
- e.addInt64(int64(u))
- }
-
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- switch v.Type() {
- case typeMongoTimestamp:
- e.addElemName(0x11, name)
- e.addInt64(v.Int())
-
- case typeOrderKey:
- if v.Int() == int64(MaxKey) {
- e.addElemName(0x7F, name)
- } else {
- e.addElemName(0xFF, name)
- }
-
- default:
- i := v.Int()
- if (minSize || v.Type().Kind() != reflect.Int64) && i >= math.MinInt32 && i <= math.MaxInt32 {
- // It fits into an int32, encode as such.
- e.addElemName(0x10, name)
- e.addInt32(int32(i))
- } else {
- e.addElemName(0x12, name)
- e.addInt64(i)
- }
- }
-
- case reflect.Bool:
- e.addElemName(0x08, name)
- if v.Bool() {
- e.addBytes(1)
- } else {
- e.addBytes(0)
- }
-
- case reflect.Map:
- e.addElemName(0x03, name)
- e.addDoc(v)
-
- case reflect.Slice:
- vt := v.Type()
- et := vt.Elem()
- if et.Kind() == reflect.Uint8 {
- e.addElemName(0x05, name)
- e.addBinary(0x00, v.Bytes())
- } else if et == typeDocElem || et == typeRawDocElem {
- e.addElemName(0x03, name)
- e.addDoc(v)
- } else {
- e.addElemName(0x04, name)
- e.addDoc(v)
- }
-
- case reflect.Array:
- et := v.Type().Elem()
- if et.Kind() == reflect.Uint8 {
- e.addElemName(0x05, name)
- if v.CanAddr() {
- e.addBinary(0x00, v.Slice(0, v.Len()).Interface().([]byte))
- } else {
- n := v.Len()
- e.addInt32(int32(n))
- e.addBytes(0x00)
- for i := 0; i < n; i++ {
- el := v.Index(i)
- e.addBytes(byte(el.Uint()))
- }
- }
- } else {
- e.addElemName(0x04, name)
- e.addDoc(v)
- }
-
- case reflect.Struct:
- switch s := v.Interface().(type) {
-
- case Raw:
- kind := s.Kind
- if kind == 0x00 {
- kind = 0x03
- }
- if len(s.Data) == 0 && kind != 0x06 && kind != 0x0A && kind != 0xFF && kind != 0x7F {
- panic("Attempted to marshal empty Raw document")
- }
- e.addElemName(kind, name)
- e.addBytes(s.Data...)
-
- case Binary:
- e.addElemName(0x05, name)
- e.addBinary(s.Kind, s.Data)
-
- case Decimal128:
- e.addElemName(0x13, name)
- e.addInt64(int64(s.l))
- e.addInt64(int64(s.h))
-
- case DBPointer:
- e.addElemName(0x0C, name)
- e.addStr(s.Namespace)
- if len(s.Id) != 12 {
- panic("ObjectIDs must be exactly 12 bytes long (got " +
- strconv.Itoa(len(s.Id)) + ")")
- }
- e.addBytes([]byte(s.Id)...)
-
- case RegEx:
- e.addElemName(0x0B, name)
- e.addCStr(s.Pattern)
- e.addCStr(s.Options)
-
- case JavaScript:
- if s.Scope == nil {
- e.addElemName(0x0D, name)
- e.addStr(s.Code)
- } else {
- e.addElemName(0x0F, name)
- start := e.reserveInt32()
- e.addStr(s.Code)
- e.addDoc(reflect.ValueOf(s.Scope))
- e.setInt32(start, int32(len(e.out)-start))
- }
-
- case time.Time:
- // MongoDB handles timestamps as milliseconds.
- e.addElemName(0x09, name)
- e.addInt64(s.Unix()*1000 + int64(s.Nanosecond()/1e6))
-
- case url.URL:
- e.addElemName(0x02, name)
- e.addStr(s.String())
-
- case undefined:
- e.addElemName(0x06, name)
-
- default:
- e.addElemName(0x03, name)
- e.addDoc(v)
- }
-
- default:
- panic("Can't marshal " + v.Type().String() + " in a BSON document")
- }
-}
-
-// --------------------------------------------------------------------------
-// Marshaling of base types.
-
-func (e *encoder) addBinary(subtype byte, v []byte) {
- if subtype == 0x02 {
- // Wonder how that brilliant idea came to life. Obsolete, luckily.
- e.addInt32(int32(len(v) + 4))
- e.addBytes(subtype)
- e.addInt32(int32(len(v)))
- } else {
- e.addInt32(int32(len(v)))
- e.addBytes(subtype)
- }
- e.addBytes(v...)
-}
-
-func (e *encoder) addStr(v string) {
- e.addInt32(int32(len(v) + 1))
- e.addCStr(v)
-}
-
-func (e *encoder) addCStr(v string) {
- e.addBytes([]byte(v)...)
- e.addBytes(0)
-}
-
-func (e *encoder) reserveInt32() (pos int) {
- pos = len(e.out)
- e.addBytes(0, 0, 0, 0)
- return pos
-}
-
-func (e *encoder) setInt32(pos int, v int32) {
- e.out[pos+0] = byte(v)
- e.out[pos+1] = byte(v >> 8)
- e.out[pos+2] = byte(v >> 16)
- e.out[pos+3] = byte(v >> 24)
-}
-
-func (e *encoder) addInt32(v int32) {
- u := uint32(v)
- e.addBytes(byte(u), byte(u>>8), byte(u>>16), byte(u>>24))
-}
-
-func (e *encoder) addInt64(v int64) {
- u := uint64(v)
- e.addBytes(byte(u), byte(u>>8), byte(u>>16), byte(u>>24),
- byte(u>>32), byte(u>>40), byte(u>>48), byte(u>>56))
-}
-
-func (e *encoder) addFloat64(v float64) {
- e.addInt64(int64(math.Float64bits(v)))
-}
-
-func (e *encoder) addBytes(v ...byte) {
- e.out = append(e.out, v...)
-}
diff --git a/vendor/gopkg.in.o/mgo.v2/bson/json.go b/vendor/gopkg.in.o/mgo.v2/bson/json.go
deleted file mode 100644
index 09df8260a..000000000
--- a/vendor/gopkg.in.o/mgo.v2/bson/json.go
+++ /dev/null
@@ -1,380 +0,0 @@
-package bson
-
-import (
- "bytes"
- "encoding/base64"
- "fmt"
- "gopkg.in/mgo.v2/internal/json"
- "strconv"
- "time"
-)
-
-// UnmarshalJSON unmarshals a JSON value that may hold non-standard
-// syntax as defined in BSON's extended JSON specification.
-func UnmarshalJSON(data []byte, value interface{}) error {
- d := json.NewDecoder(bytes.NewBuffer(data))
- d.Extend(&jsonExt)
- return d.Decode(value)
-}
-
-// MarshalJSON marshals a JSON value that may hold non-standard
-// syntax as defined in BSON's extended JSON specification.
-func MarshalJSON(value interface{}) ([]byte, error) {
- var buf bytes.Buffer
- e := json.NewEncoder(&buf)
- e.Extend(&jsonExt)
- err := e.Encode(value)
- if err != nil {
- return nil, err
- }
- return buf.Bytes(), nil
-}
-
-// jdec is used internally by the JSON decoding functions
-// so they may unmarshal functions without getting into endless
-// recursion due to keyed objects.
-func jdec(data []byte, value interface{}) error {
- d := json.NewDecoder(bytes.NewBuffer(data))
- d.Extend(&funcExt)
- return d.Decode(value)
-}
-
-var jsonExt json.Extension
-var funcExt json.Extension
-
-// TODO
-// - Shell regular expressions ("/regexp/opts")
-
-func init() {
- jsonExt.DecodeUnquotedKeys(true)
- jsonExt.DecodeTrailingCommas(true)
-
- funcExt.DecodeFunc("BinData", "$binaryFunc", "$type", "$binary")
- jsonExt.DecodeKeyed("$binary", jdecBinary)
- jsonExt.DecodeKeyed("$binaryFunc", jdecBinary)
- jsonExt.EncodeType([]byte(nil), jencBinarySlice)
- jsonExt.EncodeType(Binary{}, jencBinaryType)
-
- funcExt.DecodeFunc("ISODate", "$dateFunc", "S")
- funcExt.DecodeFunc("new Date", "$dateFunc", "S")
- jsonExt.DecodeKeyed("$date", jdecDate)
- jsonExt.DecodeKeyed("$dateFunc", jdecDate)
- jsonExt.EncodeType(time.Time{}, jencDate)
-
- funcExt.DecodeFunc("Timestamp", "$timestamp", "t", "i")
- jsonExt.DecodeKeyed("$timestamp", jdecTimestamp)
- jsonExt.EncodeType(MongoTimestamp(0), jencTimestamp)
-
- funcExt.DecodeConst("undefined", Undefined)
-
- jsonExt.DecodeKeyed("$regex", jdecRegEx)
- jsonExt.EncodeType(RegEx{}, jencRegEx)
-
- funcExt.DecodeFunc("ObjectId", "$oidFunc", "Id")
- jsonExt.DecodeKeyed("$oid", jdecObjectId)
- jsonExt.DecodeKeyed("$oidFunc", jdecObjectId)
- jsonExt.EncodeType(ObjectId(""), jencObjectId)
-
- funcExt.DecodeFunc("DBRef", "$dbrefFunc", "$ref", "$id")
- jsonExt.DecodeKeyed("$dbrefFunc", jdecDBRef)
-
- funcExt.DecodeFunc("NumberLong", "$numberLongFunc", "N")
- jsonExt.DecodeKeyed("$numberLong", jdecNumberLong)
- jsonExt.DecodeKeyed("$numberLongFunc", jdecNumberLong)
- jsonExt.EncodeType(int64(0), jencNumberLong)
- jsonExt.EncodeType(int(0), jencInt)
-
- funcExt.DecodeConst("MinKey", MinKey)
- funcExt.DecodeConst("MaxKey", MaxKey)
- jsonExt.DecodeKeyed("$minKey", jdecMinKey)
- jsonExt.DecodeKeyed("$maxKey", jdecMaxKey)
- jsonExt.EncodeType(orderKey(0), jencMinMaxKey)
-
- jsonExt.DecodeKeyed("$undefined", jdecUndefined)
- jsonExt.EncodeType(Undefined, jencUndefined)
-
- jsonExt.Extend(&funcExt)
-}
-
-func fbytes(format string, args ...interface{}) []byte {
- var buf bytes.Buffer
- fmt.Fprintf(&buf, format, args...)
- return buf.Bytes()
-}
-
-func jdecBinary(data []byte) (interface{}, error) {
- var v struct {
- Binary []byte `json:"$binary"`
- Type string `json:"$type"`
- Func struct {
- Binary []byte `json:"$binary"`
- Type int64 `json:"$type"`
- } `json:"$binaryFunc"`
- }
- err := jdec(data, &v)
- if err != nil {
- return nil, err
- }
-
- var binData []byte
- var binKind int64
- if v.Type == "" && v.Binary == nil {
- binData = v.Func.Binary
- binKind = v.Func.Type
- } else if v.Type == "" {
- return v.Binary, nil
- } else {
- binData = v.Binary
- binKind, err = strconv.ParseInt(v.Type, 0, 64)
- if err != nil {
- binKind = -1
- }
- }
-
- if binKind == 0 {
- return binData, nil
- }
- if binKind < 0 || binKind > 255 {
- return nil, fmt.Errorf("invalid type in binary object: %s", data)
- }
-
- return Binary{Kind: byte(binKind), Data: binData}, nil
-}
-
-func jencBinarySlice(v interface{}) ([]byte, error) {
- in := v.([]byte)
- out := make([]byte, base64.StdEncoding.EncodedLen(len(in)))
- base64.StdEncoding.Encode(out, in)
- return fbytes(`{"$binary":"%s","$type":"0x0"}`, out), nil
-}
-
-func jencBinaryType(v interface{}) ([]byte, error) {
- in := v.(Binary)
- out := make([]byte, base64.StdEncoding.EncodedLen(len(in.Data)))
- base64.StdEncoding.Encode(out, in.Data)
- return fbytes(`{"$binary":"%s","$type":"0x%x"}`, out, in.Kind), nil
-}
-
-const jdateFormat = "2006-01-02T15:04:05.999Z"
-
-func jdecDate(data []byte) (interface{}, error) {
- var v struct {
- S string `json:"$date"`
- Func struct {
- S string
- } `json:"$dateFunc"`
- }
- _ = jdec(data, &v)
- if v.S == "" {
- v.S = v.Func.S
- }
- if v.S != "" {
- for _, format := range []string{jdateFormat, "2006-01-02"} {
- t, err := time.Parse(format, v.S)
- if err == nil {
- return t, nil
- }
- }
- return nil, fmt.Errorf("cannot parse date: %q", v.S)
- }
-
- var vn struct {
- Date struct {
- N int64 `json:"$numberLong,string"`
- } `json:"$date"`
- Func struct {
- S int64
- } `json:"$dateFunc"`
- }
- err := jdec(data, &vn)
- if err != nil {
- return nil, fmt.Errorf("cannot parse date: %q", data)
- }
- n := vn.Date.N
- if n == 0 {
- n = vn.Func.S
- }
- return time.Unix(n/1000, n%1000*1e6).UTC(), nil
-}
-
-func jencDate(v interface{}) ([]byte, error) {
- t := v.(time.Time)
- return fbytes(`{"$date":%q}`, t.Format(jdateFormat)), nil
-}
-
-func jdecTimestamp(data []byte) (interface{}, error) {
- var v struct {
- Func struct {
- T int32 `json:"t"`
- I int32 `json:"i"`
- } `json:"$timestamp"`
- }
- err := jdec(data, &v)
- if err != nil {
- return nil, err
- }
- return MongoTimestamp(uint64(v.Func.T)<<32 | uint64(uint32(v.Func.I))), nil
-}
-
-func jencTimestamp(v interface{}) ([]byte, error) {
- ts := uint64(v.(MongoTimestamp))
- return fbytes(`{"$timestamp":{"t":%d,"i":%d}}`, ts>>32, uint32(ts)), nil
-}
-
-func jdecRegEx(data []byte) (interface{}, error) {
- var v struct {
- Regex string `json:"$regex"`
- Options string `json:"$options"`
- }
- err := jdec(data, &v)
- if err != nil {
- return nil, err
- }
- return RegEx{v.Regex, v.Options}, nil
-}
-
-func jencRegEx(v interface{}) ([]byte, error) {
- re := v.(RegEx)
- type regex struct {
- Regex string `json:"$regex"`
- Options string `json:"$options"`
- }
- return json.Marshal(regex{re.Pattern, re.Options})
-}
-
-func jdecObjectId(data []byte) (interface{}, error) {
- var v struct {
- Id string `json:"$oid"`
- Func struct {
- Id string
- } `json:"$oidFunc"`
- }
- err := jdec(data, &v)
- if err != nil {
- return nil, err
- }
- if v.Id == "" {
- v.Id = v.Func.Id
- }
- return ObjectIdHex(v.Id), nil
-}
-
-func jencObjectId(v interface{}) ([]byte, error) {
- return fbytes(`{"$oid":"%s"}`, v.(ObjectId).Hex()), nil
-}
-
-func jdecDBRef(data []byte) (interface{}, error) {
- // TODO Support unmarshaling $ref and $id into the input value.
- var v struct {
- Obj map[string]interface{} `json:"$dbrefFunc"`
- }
- // TODO Fix this. Must not be required.
- v.Obj = make(map[string]interface{})
- err := jdec(data, &v)
- if err != nil {
- return nil, err
- }
- return v.Obj, nil
-}
-
-func jdecNumberLong(data []byte) (interface{}, error) {
- var v struct {
- N int64 `json:"$numberLong,string"`
- Func struct {
- N int64 `json:",string"`
- } `json:"$numberLongFunc"`
- }
- var vn struct {
- N int64 `json:"$numberLong"`
- Func struct {
- N int64
- } `json:"$numberLongFunc"`
- }
- err := jdec(data, &v)
- if err != nil {
- err = jdec(data, &vn)
- v.N = vn.N
- v.Func.N = vn.Func.N
- }
- if err != nil {
- return nil, err
- }
- if v.N != 0 {
- return v.N, nil
- }
- return v.Func.N, nil
-}
-
-func jencNumberLong(v interface{}) ([]byte, error) {
- n := v.(int64)
- f := `{"$numberLong":"%d"}`
- if n <= 1<<53 {
- f = `{"$numberLong":%d}`
- }
- return fbytes(f, n), nil
-}
-
-func jencInt(v interface{}) ([]byte, error) {
- n := v.(int)
- f := `{"$numberLong":"%d"}`
- if int64(n) <= 1<<53 {
- f = `%d`
- }
- return fbytes(f, n), nil
-}
-
-func jdecMinKey(data []byte) (interface{}, error) {
- var v struct {
- N int64 `json:"$minKey"`
- }
- err := jdec(data, &v)
- if err != nil {
- return nil, err
- }
- if v.N != 1 {
- return nil, fmt.Errorf("invalid $minKey object: %s", data)
- }
- return MinKey, nil
-}
-
-func jdecMaxKey(data []byte) (interface{}, error) {
- var v struct {
- N int64 `json:"$maxKey"`
- }
- err := jdec(data, &v)
- if err != nil {
- return nil, err
- }
- if v.N != 1 {
- return nil, fmt.Errorf("invalid $maxKey object: %s", data)
- }
- return MaxKey, nil
-}
-
-func jencMinMaxKey(v interface{}) ([]byte, error) {
- switch v.(orderKey) {
- case MinKey:
- return []byte(`{"$minKey":1}`), nil
- case MaxKey:
- return []byte(`{"$maxKey":1}`), nil
- }
- panic(fmt.Sprintf("invalid $minKey/$maxKey value: %d", v))
-}
-
-func jdecUndefined(data []byte) (interface{}, error) {
- var v struct {
- B bool `json:"$undefined"`
- }
- err := jdec(data, &v)
- if err != nil {
- return nil, err
- }
- if !v.B {
- return nil, fmt.Errorf("invalid $undefined object: %s", data)
- }
- return Undefined, nil
-}
-
-func jencUndefined(v interface{}) ([]byte, error) {
- return []byte(`{"$undefined":true}`), nil
-}
diff --git a/vendor/gopkg.in.o/mgo.v2/bson/json_test.go b/vendor/gopkg.in.o/mgo.v2/bson/json_test.go
deleted file mode 100644
index 866f51c34..000000000
--- a/vendor/gopkg.in.o/mgo.v2/bson/json_test.go
+++ /dev/null
@@ -1,184 +0,0 @@
-package bson_test
-
-import (
- "gopkg.in/mgo.v2/bson"
-
- . "gopkg.in/check.v1"
- "reflect"
- "strings"
- "time"
-)
-
-type jsonTest struct {
- a interface{} // value encoded into JSON (optional)
- b string // JSON expected as output of , and used as input to
- c interface{} // Value expected from decoding , defaults to
- e string // error string, if decoding (b) should fail
-}
-
-var jsonTests = []jsonTest{
- // $binary
- {
- a: []byte("foo"),
- b: `{"$binary":"Zm9v","$type":"0x0"}`,
- }, {
- a: bson.Binary{Kind: 2, Data: []byte("foo")},
- b: `{"$binary":"Zm9v","$type":"0x2"}`,
- }, {
- b: `BinData(2,"Zm9v")`,
- c: bson.Binary{Kind: 2, Data: []byte("foo")},
- },
-
- // $date
- {
- a: time.Date(2016, 5, 15, 1, 2, 3, 4000000, time.UTC),
- b: `{"$date":"2016-05-15T01:02:03.004Z"}`,
- }, {
- b: `{"$date": {"$numberLong": "1002"}}`,
- c: time.Date(1970, 1, 1, 0, 0, 1, 2e6, time.UTC),
- }, {
- b: `ISODate("2016-05-15T01:02:03.004Z")`,
- c: time.Date(2016, 5, 15, 1, 2, 3, 4000000, time.UTC),
- }, {
- b: `new Date(1000)`,
- c: time.Date(1970, 1, 1, 0, 0, 1, 0, time.UTC),
- }, {
- b: `new Date("2016-05-15")`,
- c: time.Date(2016, 5, 15, 0, 0, 0, 0, time.UTC),
- },
-
- // $timestamp
- {
- a: bson.MongoTimestamp(4294967298),
- b: `{"$timestamp":{"t":1,"i":2}}`,
- }, {
- b: `Timestamp(1, 2)`,
- c: bson.MongoTimestamp(4294967298),
- },
-
- // $regex
- {
- a: bson.RegEx{"pattern", "options"},
- b: `{"$regex":"pattern","$options":"options"}`,
- },
-
- // $oid
- {
- a: bson.ObjectIdHex("0123456789abcdef01234567"),
- b: `{"$oid":"0123456789abcdef01234567"}`,
- }, {
- b: `ObjectId("0123456789abcdef01234567")`,
- c: bson.ObjectIdHex("0123456789abcdef01234567"),
- },
-
- // $ref (no special type)
- {
- b: `DBRef("name", "id")`,
- c: map[string]interface{}{"$ref": "name", "$id": "id"},
- },
-
- // $numberLong
- {
- a: 123,
- b: `123`,
- }, {
- a: int64(9007199254740992),
- b: `{"$numberLong":9007199254740992}`,
- }, {
- a: int64(1<<53 + 1),
- b: `{"$numberLong":"9007199254740993"}`,
- }, {
- a: 1<<53 + 1,
- b: `{"$numberLong":"9007199254740993"}`,
- c: int64(9007199254740993),
- }, {
- b: `NumberLong(9007199254740992)`,
- c: int64(1 << 53),
- }, {
- b: `NumberLong("9007199254740993")`,
- c: int64(1<<53 + 1),
- },
-
- // $minKey, $maxKey
- {
- a: bson.MinKey,
- b: `{"$minKey":1}`,
- }, {
- a: bson.MaxKey,
- b: `{"$maxKey":1}`,
- }, {
- b: `MinKey`,
- c: bson.MinKey,
- }, {
- b: `MaxKey`,
- c: bson.MaxKey,
- }, {
- b: `{"$minKey":0}`,
- e: `invalid $minKey object: {"$minKey":0}`,
- }, {
- b: `{"$maxKey":0}`,
- e: `invalid $maxKey object: {"$maxKey":0}`,
- },
-
- {
- a: bson.Undefined,
- b: `{"$undefined":true}`,
- }, {
- b: `undefined`,
- c: bson.Undefined,
- }, {
- b: `{"v": undefined}`,
- c: struct{ V interface{} }{bson.Undefined},
- },
-
- // Unquoted keys and trailing commas
- {
- b: `{$foo: ["bar",],}`,
- c: map[string]interface{}{"$foo": []interface{}{"bar"}},
- },
-}
-
-func (s *S) TestJSON(c *C) {
- for i, item := range jsonTests {
- c.Logf("------------ (#%d)", i)
- c.Logf("A: %#v", item.a)
- c.Logf("B: %#v", item.b)
-
- if item.c == nil {
- item.c = item.a
- } else {
- c.Logf("C: %#v", item.c)
- }
- if item.e != "" {
- c.Logf("E: %s", item.e)
- }
-
- if item.a != nil {
- data, err := bson.MarshalJSON(item.a)
- c.Assert(err, IsNil)
- c.Logf("Dumped: %#v", string(data))
- c.Assert(strings.TrimSuffix(string(data), "\n"), Equals, item.b)
- }
-
- var zero interface{}
- if item.c == nil {
- zero = &struct{}{}
- } else {
- zero = reflect.New(reflect.TypeOf(item.c)).Interface()
- }
- err := bson.UnmarshalJSON([]byte(item.b), zero)
- if item.e != "" {
- c.Assert(err, NotNil)
- c.Assert(err.Error(), Equals, item.e)
- continue
- }
- c.Assert(err, IsNil)
- zerov := reflect.ValueOf(zero)
- value := zerov.Interface()
- if zerov.Kind() == reflect.Ptr {
- value = zerov.Elem().Interface()
- }
- c.Logf("Loaded: %#v", value)
- c.Assert(value, DeepEquals, item.c)
- }
-}
diff --git a/vendor/gopkg.in.o/mgo.v2/bson/specdata/update.sh b/vendor/gopkg.in.o/mgo.v2/bson/specdata/update.sh
deleted file mode 100755
index 1efd3d3b6..000000000
--- a/vendor/gopkg.in.o/mgo.v2/bson/specdata/update.sh
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/bin/sh
-
-set -e
-
-if [ ! -d specifications ]; then
- git clone -b bson git@github.com:jyemin/specifications
-fi
-
-TESTFILE="../specdata_test.go"
-
-cat < $TESTFILE
-package bson_test
-
-var specTests = []string{
-END
-
-for file in specifications/source/bson/tests/*.yml; do
- (
- echo '`'
- cat $file
- echo -n '`,'
- ) >> $TESTFILE
-done
-
-echo '}' >> $TESTFILE
-
-gofmt -w $TESTFILE
diff --git a/vendor/gopkg.in.o/mgo.v2/bson/specdata_test.go b/vendor/gopkg.in.o/mgo.v2/bson/specdata_test.go
deleted file mode 100644
index 513f9b209..000000000
--- a/vendor/gopkg.in.o/mgo.v2/bson/specdata_test.go
+++ /dev/null
@@ -1,241 +0,0 @@
-package bson_test
-
-var specTests = []string{
- `
----
-description: "Array type"
-documents:
- -
- decoded:
- a : []
- encoded: 0D000000046100050000000000
- -
- decoded:
- a: [10]
- encoded: 140000000461000C0000001030000A0000000000
- -
- # Decode an array that uses an empty string as the key
- decodeOnly : true
- decoded:
- a: [10]
- encoded: 130000000461000B00000010000A0000000000
- -
- # Decode an array that uses a non-numeric string as the key
- decodeOnly : true
- decoded:
- a: [10]
- encoded: 150000000461000D000000106162000A0000000000
-
-
-`, `
----
-description: "Boolean type"
-documents:
- -
- encoded: "090000000862000100"
- decoded: { "b" : true }
- -
- encoded: "090000000862000000"
- decoded: { "b" : false }
-
-
- `, `
----
-description: "Corrupted BSON"
-documents:
- -
- encoded: "09000000016600"
- error: "truncated double"
- -
- encoded: "09000000026600"
- error: "truncated string"
- -
- encoded: "09000000036600"
- error: "truncated document"
- -
- encoded: "09000000046600"
- error: "truncated array"
- -
- encoded: "09000000056600"
- error: "truncated binary"
- -
- encoded: "09000000076600"
- error: "truncated objectid"
- -
- encoded: "09000000086600"
- error: "truncated boolean"
- -
- encoded: "09000000096600"
- error: "truncated date"
- -
- encoded: "090000000b6600"
- error: "truncated regex"
- -
- encoded: "090000000c6600"
- error: "truncated db pointer"
- -
- encoded: "0C0000000d6600"
- error: "truncated javascript"
- -
- encoded: "0C0000000e6600"
- error: "truncated symbol"
- -
- encoded: "0C0000000f6600"
- error: "truncated javascript with scope"
- -
- encoded: "0C000000106600"
- error: "truncated int32"
- -
- encoded: "0C000000116600"
- error: "truncated timestamp"
- -
- encoded: "0C000000126600"
- error: "truncated int64"
- -
- encoded: "0400000000"
- error: basic
- -
- encoded: "0500000001"
- error: basic
- -
- encoded: "05000000"
- error: basic
- -
- encoded: "0700000002610078563412"
- error: basic
- -
- encoded: "090000001061000500"
- error: basic
- -
- encoded: "00000000000000000000"
- error: basic
- -
- encoded: "1300000002666f6f00040000006261720000"
- error: "basic"
- -
- encoded: "1800000003666f6f000f0000001062617200ffffff7f0000"
- error: basic
- -
- encoded: "1500000003666f6f000c0000000862617200010000"
- error: basic
- -
- encoded: "1c00000003666f6f001200000002626172000500000062617a000000"
- error: basic
- -
- encoded: "1000000002610004000000616263ff00"
- error: string is not null-terminated
- -
- encoded: "0c0000000200000000000000"
- error: bad_string_length
- -
- encoded: "120000000200ffffffff666f6f6261720000"
- error: bad_string_length
- -
- encoded: "0c0000000e00000000000000"
- error: bad_string_length
- -
- encoded: "120000000e00ffffffff666f6f6261720000"
- error: bad_string_length
- -
- encoded: "180000000c00fa5bd841d6585d9900"
- error: ""
- -
- encoded: "1e0000000c00ffffffff666f6f626172005259b56afa5bd841d6585d9900"
- error: bad_string_length
- -
- encoded: "0c0000000d00000000000000"
- error: bad_string_length
- -
- encoded: "0c0000000d00ffffffff0000"
- error: bad_string_length
- -
- encoded: "1c0000000f001500000000000000000c000000020001000000000000"
- error: bad_string_length
- -
- encoded: "1c0000000f0015000000ffffffff000c000000020001000000000000"
- error: bad_string_length
- -
- encoded: "1c0000000f001500000001000000000c000000020000000000000000"
- error: bad_string_length
- -
- encoded: "1c0000000f001500000001000000000c0000000200ffffffff000000"
- error: bad_string_length
- -
- encoded: "0E00000008616263646566676869707172737475"
- error: "Run-on CString"
- -
- encoded: "0100000000"
- error: "An object size that's too small to even include the object size, but is correctly encoded, along with a correct EOO (and no data)"
- -
- encoded: "1a0000000e74657374000c00000068656c6c6f20776f726c6400000500000000"
- error: "One object, but with object size listed smaller than it is in the data"
- -
- encoded: "05000000"
- error: "One object, missing the EOO at the end"
- -
- encoded: "0500000001"
- error: "One object, sized correctly, with a spot for an EOO, but the EOO is 0x01"
- -
- encoded: "05000000ff"
- error: "One object, sized correctly, with a spot for an EOO, but the EOO is 0xff"
- -
- encoded: "0500000070"
- error: "One object, sized correctly, with a spot for an EOO, but the EOO is 0x70"
- -
- encoded: "07000000000000"
- error: "Invalid BSON type low range"
- -
- encoded: "07000000800000"
- error: "Invalid BSON type high range"
- -
- encoded: "090000000862000200"
- error: "Invalid boolean value of 2"
- -
- encoded: "09000000086200ff00"
- error: "Invalid boolean value of -1"
- `, `
----
-description: "Int32 type"
-documents:
- -
- decoded:
- i: -2147483648
- encoded: 0C0000001069000000008000
- -
- decoded:
- i: 2147483647
- encoded: 0C000000106900FFFFFF7F00
- -
- decoded:
- i: -1
- encoded: 0C000000106900FFFFFFFF00
- -
- decoded:
- i: 0
- encoded: 0C0000001069000000000000
- -
- decoded:
- i: 1
- encoded: 0C0000001069000100000000
-
-`, `
----
-description: "String type"
-documents:
- -
- decoded:
- s : ""
- encoded: 0D000000027300010000000000
- -
- decoded:
- s: "a"
- encoded: 0E00000002730002000000610000
- -
- decoded:
- s: "This is a string"
- encoded: 1D0000000273001100000054686973206973206120737472696E670000
- -
- decoded:
- s: "κόσμε"
- encoded: 180000000273000C000000CEBAE1BDB9CF83CEBCCEB50000
-`}
diff --git a/vendor/gopkg.in.o/mgo.v2/internal/json/bench_test.go b/vendor/gopkg.in.o/mgo.v2/internal/json/bench_test.go
deleted file mode 100644
index cd7380b1e..000000000
--- a/vendor/gopkg.in.o/mgo.v2/internal/json/bench_test.go
+++ /dev/null
@@ -1,223 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Large data benchmark.
-// The JSON data is a summary of agl's changes in the
-// go, webkit, and chromium open source projects.
-// We benchmark converting between the JSON form
-// and in-memory data structures.
-
-package json
-
-import (
- "bytes"
- "compress/gzip"
- "io/ioutil"
- "os"
- "strings"
- "testing"
-)
-
-type codeResponse struct {
- Tree *codeNode `json:"tree"`
- Username string `json:"username"`
-}
-
-type codeNode struct {
- Name string `json:"name"`
- Kids []*codeNode `json:"kids"`
- CLWeight float64 `json:"cl_weight"`
- Touches int `json:"touches"`
- MinT int64 `json:"min_t"`
- MaxT int64 `json:"max_t"`
- MeanT int64 `json:"mean_t"`
-}
-
-var codeJSON []byte
-var codeStruct codeResponse
-
-func codeInit() {
- f, err := os.Open("testdata/code.json.gz")
- if err != nil {
- panic(err)
- }
- defer f.Close()
- gz, err := gzip.NewReader(f)
- if err != nil {
- panic(err)
- }
- data, err := ioutil.ReadAll(gz)
- if err != nil {
- panic(err)
- }
-
- codeJSON = data
-
- if err := Unmarshal(codeJSON, &codeStruct); err != nil {
- panic("unmarshal code.json: " + err.Error())
- }
-
- if data, err = Marshal(&codeStruct); err != nil {
- panic("marshal code.json: " + err.Error())
- }
-
- if !bytes.Equal(data, codeJSON) {
- println("different lengths", len(data), len(codeJSON))
- for i := 0; i < len(data) && i < len(codeJSON); i++ {
- if data[i] != codeJSON[i] {
- println("re-marshal: changed at byte", i)
- println("orig: ", string(codeJSON[i-10:i+10]))
- println("new: ", string(data[i-10:i+10]))
- break
- }
- }
- panic("re-marshal code.json: different result")
- }
-}
-
-func BenchmarkCodeEncoder(b *testing.B) {
- if codeJSON == nil {
- b.StopTimer()
- codeInit()
- b.StartTimer()
- }
- enc := NewEncoder(ioutil.Discard)
- for i := 0; i < b.N; i++ {
- if err := enc.Encode(&codeStruct); err != nil {
- b.Fatal("Encode:", err)
- }
- }
- b.SetBytes(int64(len(codeJSON)))
-}
-
-func BenchmarkCodeMarshal(b *testing.B) {
- if codeJSON == nil {
- b.StopTimer()
- codeInit()
- b.StartTimer()
- }
- for i := 0; i < b.N; i++ {
- if _, err := Marshal(&codeStruct); err != nil {
- b.Fatal("Marshal:", err)
- }
- }
- b.SetBytes(int64(len(codeJSON)))
-}
-
-func BenchmarkCodeDecoder(b *testing.B) {
- if codeJSON == nil {
- b.StopTimer()
- codeInit()
- b.StartTimer()
- }
- var buf bytes.Buffer
- dec := NewDecoder(&buf)
- var r codeResponse
- for i := 0; i < b.N; i++ {
- buf.Write(codeJSON)
- // hide EOF
- buf.WriteByte('\n')
- buf.WriteByte('\n')
- buf.WriteByte('\n')
- if err := dec.Decode(&r); err != nil {
- b.Fatal("Decode:", err)
- }
- }
- b.SetBytes(int64(len(codeJSON)))
-}
-
-func BenchmarkDecoderStream(b *testing.B) {
- b.StopTimer()
- var buf bytes.Buffer
- dec := NewDecoder(&buf)
- buf.WriteString(`"` + strings.Repeat("x", 1000000) + `"` + "\n\n\n")
- var x interface{}
- if err := dec.Decode(&x); err != nil {
- b.Fatal("Decode:", err)
- }
- ones := strings.Repeat(" 1\n", 300000) + "\n\n\n"
- b.StartTimer()
- for i := 0; i < b.N; i++ {
- if i%300000 == 0 {
- buf.WriteString(ones)
- }
- x = nil
- if err := dec.Decode(&x); err != nil || x != 1.0 {
- b.Fatalf("Decode: %v after %d", err, i)
- }
- }
-}
-
-func BenchmarkCodeUnmarshal(b *testing.B) {
- if codeJSON == nil {
- b.StopTimer()
- codeInit()
- b.StartTimer()
- }
- for i := 0; i < b.N; i++ {
- var r codeResponse
- if err := Unmarshal(codeJSON, &r); err != nil {
- b.Fatal("Unmarshal:", err)
- }
- }
- b.SetBytes(int64(len(codeJSON)))
-}
-
-func BenchmarkCodeUnmarshalReuse(b *testing.B) {
- if codeJSON == nil {
- b.StopTimer()
- codeInit()
- b.StartTimer()
- }
- var r codeResponse
- for i := 0; i < b.N; i++ {
- if err := Unmarshal(codeJSON, &r); err != nil {
- b.Fatal("Unmarshal:", err)
- }
- }
-}
-
-func BenchmarkUnmarshalString(b *testing.B) {
- data := []byte(`"hello, world"`)
- var s string
-
- for i := 0; i < b.N; i++ {
- if err := Unmarshal(data, &s); err != nil {
- b.Fatal("Unmarshal:", err)
- }
- }
-}
-
-func BenchmarkUnmarshalFloat64(b *testing.B) {
- var f float64
- data := []byte(`3.14`)
-
- for i := 0; i < b.N; i++ {
- if err := Unmarshal(data, &f); err != nil {
- b.Fatal("Unmarshal:", err)
- }
- }
-}
-
-func BenchmarkUnmarshalInt64(b *testing.B) {
- var x int64
- data := []byte(`3`)
-
- for i := 0; i < b.N; i++ {
- if err := Unmarshal(data, &x); err != nil {
- b.Fatal("Unmarshal:", err)
- }
- }
-}
-
-func BenchmarkIssue10335(b *testing.B) {
- b.ReportAllocs()
- var s struct{}
- j := []byte(`{"a":{ }}`)
- for n := 0; n < b.N; n++ {
- if err := Unmarshal(j, &s); err != nil {
- b.Fatal(err)
- }
- }
-}
diff --git a/vendor/gopkg.in.o/mgo.v2/internal/json/decode.go b/vendor/gopkg.in.o/mgo.v2/internal/json/decode.go
deleted file mode 100644
index ce7c7d249..000000000
--- a/vendor/gopkg.in.o/mgo.v2/internal/json/decode.go
+++ /dev/null
@@ -1,1685 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Represents JSON data structure using native Go types: booleans, floats,
-// strings, arrays, and maps.
-
-package json
-
-import (
- "bytes"
- "encoding"
- "encoding/base64"
- "errors"
- "fmt"
- "reflect"
- "runtime"
- "strconv"
- "unicode"
- "unicode/utf16"
- "unicode/utf8"
-)
-
-// Unmarshal parses the JSON-encoded data and stores the result
-// in the value pointed to by v.
-//
-// Unmarshal uses the inverse of the encodings that
-// Marshal uses, allocating maps, slices, and pointers as necessary,
-// with the following additional rules:
-//
-// To unmarshal JSON into a pointer, Unmarshal first handles the case of
-// the JSON being the JSON literal null. In that case, Unmarshal sets
-// the pointer to nil. Otherwise, Unmarshal unmarshals the JSON into
-// the value pointed at by the pointer. If the pointer is nil, Unmarshal
-// allocates a new value for it to point to.
-//
-// To unmarshal JSON into a struct, Unmarshal matches incoming object
-// keys to the keys used by Marshal (either the struct field name or its tag),
-// preferring an exact match but also accepting a case-insensitive match.
-// Unmarshal will only set exported fields of the struct.
-//
-// To unmarshal JSON into an interface value,
-// Unmarshal stores one of these in the interface value:
-//
-// bool, for JSON booleans
-// float64, for JSON numbers
-// string, for JSON strings
-// []interface{}, for JSON arrays
-// map[string]interface{}, for JSON objects
-// nil for JSON null
-//
-// To unmarshal a JSON array into a slice, Unmarshal resets the slice length
-// to zero and then appends each element to the slice.
-// As a special case, to unmarshal an empty JSON array into a slice,
-// Unmarshal replaces the slice with a new empty slice.
-//
-// To unmarshal a JSON array into a Go array, Unmarshal decodes
-// JSON array elements into corresponding Go array elements.
-// If the Go array is smaller than the JSON array,
-// the additional JSON array elements are discarded.
-// If the JSON array is smaller than the Go array,
-// the additional Go array elements are set to zero values.
-//
-// To unmarshal a JSON object into a map, Unmarshal first establishes a map to
-// use, If the map is nil, Unmarshal allocates a new map. Otherwise Unmarshal
-// reuses the existing map, keeping existing entries. Unmarshal then stores key-
-// value pairs from the JSON object into the map. The map's key type must
-// either be a string or implement encoding.TextUnmarshaler.
-//
-// If a JSON value is not appropriate for a given target type,
-// or if a JSON number overflows the target type, Unmarshal
-// skips that field and completes the unmarshaling as best it can.
-// If no more serious errors are encountered, Unmarshal returns
-// an UnmarshalTypeError describing the earliest such error.
-//
-// The JSON null value unmarshals into an interface, map, pointer, or slice
-// by setting that Go value to nil. Because null is often used in JSON to mean
-// ``not present,'' unmarshaling a JSON null into any other Go type has no effect
-// on the value and produces no error.
-//
-// When unmarshaling quoted strings, invalid UTF-8 or
-// invalid UTF-16 surrogate pairs are not treated as an error.
-// Instead, they are replaced by the Unicode replacement
-// character U+FFFD.
-//
-func Unmarshal(data []byte, v interface{}) error {
- // Check for well-formedness.
- // Avoids filling out half a data structure
- // before discovering a JSON syntax error.
- var d decodeState
- err := checkValid(data, &d.scan)
- if err != nil {
- return err
- }
-
- d.init(data)
- return d.unmarshal(v)
-}
-
-// Unmarshaler is the interface implemented by types
-// that can unmarshal a JSON description of themselves.
-// The input can be assumed to be a valid encoding of
-// a JSON value. UnmarshalJSON must copy the JSON data
-// if it wishes to retain the data after returning.
-type Unmarshaler interface {
- UnmarshalJSON([]byte) error
-}
-
-// An UnmarshalTypeError describes a JSON value that was
-// not appropriate for a value of a specific Go type.
-type UnmarshalTypeError struct {
- Value string // description of JSON value - "bool", "array", "number -5"
- Type reflect.Type // type of Go value it could not be assigned to
- Offset int64 // error occurred after reading Offset bytes
-}
-
-func (e *UnmarshalTypeError) Error() string {
- return "json: cannot unmarshal " + e.Value + " into Go value of type " + e.Type.String()
-}
-
-// An UnmarshalFieldError describes a JSON object key that
-// led to an unexported (and therefore unwritable) struct field.
-// (No longer used; kept for compatibility.)
-type UnmarshalFieldError struct {
- Key string
- Type reflect.Type
- Field reflect.StructField
-}
-
-func (e *UnmarshalFieldError) Error() string {
- return "json: cannot unmarshal object key " + strconv.Quote(e.Key) + " into unexported field " + e.Field.Name + " of type " + e.Type.String()
-}
-
-// An InvalidUnmarshalError describes an invalid argument passed to Unmarshal.
-// (The argument to Unmarshal must be a non-nil pointer.)
-type InvalidUnmarshalError struct {
- Type reflect.Type
-}
-
-func (e *InvalidUnmarshalError) Error() string {
- if e.Type == nil {
- return "json: Unmarshal(nil)"
- }
-
- if e.Type.Kind() != reflect.Ptr {
- return "json: Unmarshal(non-pointer " + e.Type.String() + ")"
- }
- return "json: Unmarshal(nil " + e.Type.String() + ")"
-}
-
-func (d *decodeState) unmarshal(v interface{}) (err error) {
- defer func() {
- if r := recover(); r != nil {
- if _, ok := r.(runtime.Error); ok {
- panic(r)
- }
- err = r.(error)
- }
- }()
-
- rv := reflect.ValueOf(v)
- if rv.Kind() != reflect.Ptr || rv.IsNil() {
- return &InvalidUnmarshalError{reflect.TypeOf(v)}
- }
-
- d.scan.reset()
- // We decode rv not rv.Elem because the Unmarshaler interface
- // test must be applied at the top level of the value.
- d.value(rv)
- return d.savedError
-}
-
-// A Number represents a JSON number literal.
-type Number string
-
-// String returns the literal text of the number.
-func (n Number) String() string { return string(n) }
-
-// Float64 returns the number as a float64.
-func (n Number) Float64() (float64, error) {
- return strconv.ParseFloat(string(n), 64)
-}
-
-// Int64 returns the number as an int64.
-func (n Number) Int64() (int64, error) {
- return strconv.ParseInt(string(n), 10, 64)
-}
-
-// isValidNumber reports whether s is a valid JSON number literal.
-func isValidNumber(s string) bool {
- // This function implements the JSON numbers grammar.
- // See https://tools.ietf.org/html/rfc7159#section-6
- // and http://json.org/number.gif
-
- if s == "" {
- return false
- }
-
- // Optional -
- if s[0] == '-' {
- s = s[1:]
- if s == "" {
- return false
- }
- }
-
- // Digits
- switch {
- default:
- return false
-
- case s[0] == '0':
- s = s[1:]
-
- case '1' <= s[0] && s[0] <= '9':
- s = s[1:]
- for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
- s = s[1:]
- }
- }
-
- // . followed by 1 or more digits.
- if len(s) >= 2 && s[0] == '.' && '0' <= s[1] && s[1] <= '9' {
- s = s[2:]
- for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
- s = s[1:]
- }
- }
-
- // e or E followed by an optional - or + and
- // 1 or more digits.
- if len(s) >= 2 && (s[0] == 'e' || s[0] == 'E') {
- s = s[1:]
- if s[0] == '+' || s[0] == '-' {
- s = s[1:]
- if s == "" {
- return false
- }
- }
- for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
- s = s[1:]
- }
- }
-
- // Make sure we are at the end.
- return s == ""
-}
-
-// decodeState represents the state while decoding a JSON value.
-type decodeState struct {
- data []byte
- off int // read offset in data
- scan scanner
- nextscan scanner // for calls to nextValue
- savedError error
- useNumber bool
- ext Extension
-}
-
-// errPhase is used for errors that should not happen unless
-// there is a bug in the JSON decoder or something is editing
-// the data slice while the decoder executes.
-var errPhase = errors.New("JSON decoder out of sync - data changing underfoot?")
-
-func (d *decodeState) init(data []byte) *decodeState {
- d.data = data
- d.off = 0
- d.savedError = nil
- return d
-}
-
-// error aborts the decoding by panicking with err.
-func (d *decodeState) error(err error) {
- panic(err)
-}
-
-// saveError saves the first err it is called with,
-// for reporting at the end of the unmarshal.
-func (d *decodeState) saveError(err error) {
- if d.savedError == nil {
- d.savedError = err
- }
-}
-
-// next cuts off and returns the next full JSON value in d.data[d.off:].
-// The next value is known to be an object or array, not a literal.
-func (d *decodeState) next() []byte {
- c := d.data[d.off]
- item, rest, err := nextValue(d.data[d.off:], &d.nextscan)
- if err != nil {
- d.error(err)
- }
- d.off = len(d.data) - len(rest)
-
- // Our scanner has seen the opening brace/bracket
- // and thinks we're still in the middle of the object.
- // invent a closing brace/bracket to get it out.
- if c == '{' {
- d.scan.step(&d.scan, '}')
- } else if c == '[' {
- d.scan.step(&d.scan, ']')
- } else {
- // Was inside a function name. Get out of it.
- d.scan.step(&d.scan, '(')
- d.scan.step(&d.scan, ')')
- }
-
- return item
-}
-
-// scanWhile processes bytes in d.data[d.off:] until it
-// receives a scan code not equal to op.
-// It updates d.off and returns the new scan code.
-func (d *decodeState) scanWhile(op int) int {
- var newOp int
- for {
- if d.off >= len(d.data) {
- newOp = d.scan.eof()
- d.off = len(d.data) + 1 // mark processed EOF with len+1
- } else {
- c := d.data[d.off]
- d.off++
- newOp = d.scan.step(&d.scan, c)
- }
- if newOp != op {
- break
- }
- }
- return newOp
-}
-
-// value decodes a JSON value from d.data[d.off:] into the value.
-// it updates d.off to point past the decoded value.
-func (d *decodeState) value(v reflect.Value) {
- if !v.IsValid() {
- _, rest, err := nextValue(d.data[d.off:], &d.nextscan)
- if err != nil {
- d.error(err)
- }
- d.off = len(d.data) - len(rest)
-
- // d.scan thinks we're still at the beginning of the item.
- // Feed in an empty string - the shortest, simplest value -
- // so that it knows we got to the end of the value.
- if d.scan.redo {
- // rewind.
- d.scan.redo = false
- d.scan.step = stateBeginValue
- }
- d.scan.step(&d.scan, '"')
- d.scan.step(&d.scan, '"')
-
- n := len(d.scan.parseState)
- if n > 0 && d.scan.parseState[n-1] == parseObjectKey {
- // d.scan thinks we just read an object key; finish the object
- d.scan.step(&d.scan, ':')
- d.scan.step(&d.scan, '"')
- d.scan.step(&d.scan, '"')
- d.scan.step(&d.scan, '}')
- }
-
- return
- }
-
- switch op := d.scanWhile(scanSkipSpace); op {
- default:
- d.error(errPhase)
-
- case scanBeginArray:
- d.array(v)
-
- case scanBeginObject:
- d.object(v)
-
- case scanBeginLiteral:
- d.literal(v)
-
- case scanBeginName:
- d.name(v)
- }
-}
-
-type unquotedValue struct{}
-
-// valueQuoted is like value but decodes a
-// quoted string literal or literal null into an interface value.
-// If it finds anything other than a quoted string literal or null,
-// valueQuoted returns unquotedValue{}.
-func (d *decodeState) valueQuoted() interface{} {
- switch op := d.scanWhile(scanSkipSpace); op {
- default:
- d.error(errPhase)
-
- case scanBeginArray:
- d.array(reflect.Value{})
-
- case scanBeginObject:
- d.object(reflect.Value{})
-
- case scanBeginName:
- switch v := d.nameInterface().(type) {
- case nil, string:
- return v
- }
-
- case scanBeginLiteral:
- switch v := d.literalInterface().(type) {
- case nil, string:
- return v
- }
- }
- return unquotedValue{}
-}
-
-// indirect walks down v allocating pointers as needed,
-// until it gets to a non-pointer.
-// if it encounters an Unmarshaler, indirect stops and returns that.
-// if decodingNull is true, indirect stops at the last pointer so it can be set to nil.
-func (d *decodeState) indirect(v reflect.Value, decodingNull bool) (Unmarshaler, encoding.TextUnmarshaler, reflect.Value) {
- // If v is a named type and is addressable,
- // start with its address, so that if the type has pointer methods,
- // we find them.
- if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() {
- v = v.Addr()
- }
- for {
- // Load value from interface, but only if the result will be
- // usefully addressable.
- if v.Kind() == reflect.Interface && !v.IsNil() {
- e := v.Elem()
- if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Ptr) {
- v = e
- continue
- }
- }
-
- if v.Kind() != reflect.Ptr {
- break
- }
-
- if v.Elem().Kind() != reflect.Ptr && decodingNull && v.CanSet() {
- break
- }
- if v.IsNil() {
- v.Set(reflect.New(v.Type().Elem()))
- }
- if v.Type().NumMethod() > 0 {
- if u, ok := v.Interface().(Unmarshaler); ok {
- return u, nil, v
- }
- if u, ok := v.Interface().(encoding.TextUnmarshaler); ok {
- return nil, u, v
- }
- }
- v = v.Elem()
- }
- return nil, nil, v
-}
-
-// array consumes an array from d.data[d.off-1:], decoding into the value v.
-// the first byte of the array ('[') has been read already.
-func (d *decodeState) array(v reflect.Value) {
- // Check for unmarshaler.
- u, ut, pv := d.indirect(v, false)
- if u != nil {
- d.off--
- err := u.UnmarshalJSON(d.next())
- if err != nil {
- d.error(err)
- }
- return
- }
- if ut != nil {
- d.saveError(&UnmarshalTypeError{"array", v.Type(), int64(d.off)})
- d.off--
- d.next()
- return
- }
-
- v = pv
-
- // Check type of target.
- switch v.Kind() {
- case reflect.Interface:
- if v.NumMethod() == 0 {
- // Decoding into nil interface? Switch to non-reflect code.
- v.Set(reflect.ValueOf(d.arrayInterface()))
- return
- }
- // Otherwise it's invalid.
- fallthrough
- default:
- d.saveError(&UnmarshalTypeError{"array", v.Type(), int64(d.off)})
- d.off--
- d.next()
- return
- case reflect.Array:
- case reflect.Slice:
- break
- }
-
- i := 0
- for {
- // Look ahead for ] - can only happen on first iteration.
- op := d.scanWhile(scanSkipSpace)
- if op == scanEndArray {
- break
- }
-
- // Back up so d.value can have the byte we just read.
- d.off--
- d.scan.undo(op)
-
- // Get element of array, growing if necessary.
- if v.Kind() == reflect.Slice {
- // Grow slice if necessary
- if i >= v.Cap() {
- newcap := v.Cap() + v.Cap()/2
- if newcap < 4 {
- newcap = 4
- }
- newv := reflect.MakeSlice(v.Type(), v.Len(), newcap)
- reflect.Copy(newv, v)
- v.Set(newv)
- }
- if i >= v.Len() {
- v.SetLen(i + 1)
- }
- }
-
- if i < v.Len() {
- // Decode into element.
- d.value(v.Index(i))
- } else {
- // Ran out of fixed array: skip.
- d.value(reflect.Value{})
- }
- i++
-
- // Next token must be , or ].
- op = d.scanWhile(scanSkipSpace)
- if op == scanEndArray {
- break
- }
- if op != scanArrayValue {
- d.error(errPhase)
- }
- }
-
- if i < v.Len() {
- if v.Kind() == reflect.Array {
- // Array. Zero the rest.
- z := reflect.Zero(v.Type().Elem())
- for ; i < v.Len(); i++ {
- v.Index(i).Set(z)
- }
- } else {
- v.SetLen(i)
- }
- }
- if i == 0 && v.Kind() == reflect.Slice {
- v.Set(reflect.MakeSlice(v.Type(), 0, 0))
- }
-}
-
-var nullLiteral = []byte("null")
-var textUnmarshalerType = reflect.TypeOf(new(encoding.TextUnmarshaler)).Elem()
-
-// object consumes an object from d.data[d.off-1:], decoding into the value v.
-// the first byte ('{') of the object has been read already.
-func (d *decodeState) object(v reflect.Value) {
- // Check for unmarshaler.
- u, ut, pv := d.indirect(v, false)
- if d.storeKeyed(pv) {
- return
- }
- if u != nil {
- d.off--
- err := u.UnmarshalJSON(d.next())
- if err != nil {
- d.error(err)
- }
- return
- }
- if ut != nil {
- d.saveError(&UnmarshalTypeError{"object", v.Type(), int64(d.off)})
- d.off--
- d.next() // skip over { } in input
- return
- }
- v = pv
-
- // Decoding into nil interface? Switch to non-reflect code.
- if v.Kind() == reflect.Interface && v.NumMethod() == 0 {
- v.Set(reflect.ValueOf(d.objectInterface()))
- return
- }
-
- // Check type of target:
- // struct or
- // map[string]T or map[encoding.TextUnmarshaler]T
- switch v.Kind() {
- case reflect.Map:
- // Map key must either have string kind or be an encoding.TextUnmarshaler.
- t := v.Type()
- if t.Key().Kind() != reflect.String &&
- !reflect.PtrTo(t.Key()).Implements(textUnmarshalerType) {
- d.saveError(&UnmarshalTypeError{"object", v.Type(), int64(d.off)})
- d.off--
- d.next() // skip over { } in input
- return
- }
- if v.IsNil() {
- v.Set(reflect.MakeMap(t))
- }
- case reflect.Struct:
-
- default:
- d.saveError(&UnmarshalTypeError{"object", v.Type(), int64(d.off)})
- d.off--
- d.next() // skip over { } in input
- return
- }
-
- var mapElem reflect.Value
-
- empty := true
- for {
- // Read opening " of string key or closing }.
- op := d.scanWhile(scanSkipSpace)
- if op == scanEndObject {
- if !empty && !d.ext.trailingCommas {
- d.syntaxError("beginning of object key string")
- }
- break
- }
- empty = false
- if op == scanBeginName {
- if !d.ext.unquotedKeys {
- d.syntaxError("beginning of object key string")
- }
- } else if op != scanBeginLiteral {
- d.error(errPhase)
- }
- unquotedKey := op == scanBeginName
-
- // Read key.
- start := d.off - 1
- op = d.scanWhile(scanContinue)
- item := d.data[start : d.off-1]
- var key []byte
- if unquotedKey {
- key = item
- // TODO Fix code below to quote item when necessary.
- } else {
- var ok bool
- key, ok = unquoteBytes(item)
- if !ok {
- d.error(errPhase)
- }
- }
-
- // Figure out field corresponding to key.
- var subv reflect.Value
- destring := false // whether the value is wrapped in a string to be decoded first
-
- if v.Kind() == reflect.Map {
- elemType := v.Type().Elem()
- if !mapElem.IsValid() {
- mapElem = reflect.New(elemType).Elem()
- } else {
- mapElem.Set(reflect.Zero(elemType))
- }
- subv = mapElem
- } else {
- var f *field
- fields := cachedTypeFields(v.Type())
- for i := range fields {
- ff := &fields[i]
- if bytes.Equal(ff.nameBytes, key) {
- f = ff
- break
- }
- if f == nil && ff.equalFold(ff.nameBytes, key) {
- f = ff
- }
- }
- if f != nil {
- subv = v
- destring = f.quoted
- for _, i := range f.index {
- if subv.Kind() == reflect.Ptr {
- if subv.IsNil() {
- subv.Set(reflect.New(subv.Type().Elem()))
- }
- subv = subv.Elem()
- }
- subv = subv.Field(i)
- }
- }
- }
-
- // Read : before value.
- if op == scanSkipSpace {
- op = d.scanWhile(scanSkipSpace)
- }
- if op != scanObjectKey {
- d.error(errPhase)
- }
-
- // Read value.
- if destring {
- switch qv := d.valueQuoted().(type) {
- case nil:
- d.literalStore(nullLiteral, subv, false)
- case string:
- d.literalStore([]byte(qv), subv, true)
- default:
- d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal unquoted value into %v", subv.Type()))
- }
- } else {
- d.value(subv)
- }
-
- // Write value back to map;
- // if using struct, subv points into struct already.
- if v.Kind() == reflect.Map {
- kt := v.Type().Key()
- var kv reflect.Value
- switch {
- case kt.Kind() == reflect.String:
- kv = reflect.ValueOf(key).Convert(v.Type().Key())
- case reflect.PtrTo(kt).Implements(textUnmarshalerType):
- kv = reflect.New(v.Type().Key())
- d.literalStore(item, kv, true)
- kv = kv.Elem()
- default:
- panic("json: Unexpected key type") // should never occur
- }
- v.SetMapIndex(kv, subv)
- }
-
- // Next token must be , or }.
- op = d.scanWhile(scanSkipSpace)
- if op == scanEndObject {
- break
- }
- if op != scanObjectValue {
- d.error(errPhase)
- }
- }
-}
-
-// isNull returns whether there's a null literal at the provided offset.
-func (d *decodeState) isNull(off int) bool {
- if off+4 >= len(d.data) || d.data[off] != 'n' || d.data[off+1] != 'u' || d.data[off+2] != 'l' || d.data[off+3] != 'l' {
- return false
- }
- d.nextscan.reset()
- for i, c := range d.data[off:] {
- if i > 4 {
- return false
- }
- switch d.nextscan.step(&d.nextscan, c) {
- case scanContinue, scanBeginName:
- continue
- }
- break
- }
- return true
-}
-
-// name consumes a const or function from d.data[d.off-1:], decoding into the value v.
-// the first byte of the function name has been read already.
-func (d *decodeState) name(v reflect.Value) {
- if d.isNull(d.off-1) {
- d.literal(v)
- return
- }
-
- // Check for unmarshaler.
- u, ut, pv := d.indirect(v, false)
- if d.storeKeyed(pv) {
- return
- }
- if u != nil {
- d.off--
- err := u.UnmarshalJSON(d.next())
- if err != nil {
- d.error(err)
- }
- return
- }
- if ut != nil {
- d.saveError(&UnmarshalTypeError{"object", v.Type(), int64(d.off)})
- d.off--
- d.next() // skip over function in input
- return
- }
- v = pv
-
- // Decoding into nil interface? Switch to non-reflect code.
- if v.Kind() == reflect.Interface && v.NumMethod() == 0 {
- out := d.nameInterface()
- if out == nil {
- v.Set(reflect.Zero(v.Type()))
- } else {
- v.Set(reflect.ValueOf(out))
- }
- return
- }
-
- nameStart := d.off - 1
-
- op := d.scanWhile(scanContinue)
-
- name := d.data[nameStart : d.off-1]
- if op != scanParam {
- // Back up so the byte just read is consumed next.
- d.off--
- d.scan.undo(op)
- if l, ok := d.convertLiteral(name); ok {
- d.storeValue(v, l)
- return
- }
- d.error(&SyntaxError{fmt.Sprintf("json: unknown constant %q", name), int64(d.off)})
- }
-
- funcName := string(name)
- funcData := d.ext.funcs[funcName]
- if funcData.key == "" {
- d.error(fmt.Errorf("json: unknown function %q", funcName))
- }
-
- // Check type of target:
- // struct or
- // map[string]T or map[encoding.TextUnmarshaler]T
- switch v.Kind() {
- case reflect.Map:
- // Map key must either have string kind or be an encoding.TextUnmarshaler.
- t := v.Type()
- if t.Key().Kind() != reflect.String &&
- !reflect.PtrTo(t.Key()).Implements(textUnmarshalerType) {
- d.saveError(&UnmarshalTypeError{"object", v.Type(), int64(d.off)})
- d.off--
- d.next() // skip over { } in input
- return
- }
- if v.IsNil() {
- v.Set(reflect.MakeMap(t))
- }
- case reflect.Struct:
-
- default:
- d.saveError(&UnmarshalTypeError{"object", v.Type(), int64(d.off)})
- d.off--
- d.next() // skip over { } in input
- return
- }
-
- // TODO Fix case of func field as map.
- //topv := v
-
- // Figure out field corresponding to function.
- key := []byte(funcData.key)
- if v.Kind() == reflect.Map {
- elemType := v.Type().Elem()
- v = reflect.New(elemType).Elem()
- } else {
- var f *field
- fields := cachedTypeFields(v.Type())
- for i := range fields {
- ff := &fields[i]
- if bytes.Equal(ff.nameBytes, key) {
- f = ff
- break
- }
- if f == nil && ff.equalFold(ff.nameBytes, key) {
- f = ff
- }
- }
- if f != nil {
- for _, i := range f.index {
- if v.Kind() == reflect.Ptr {
- if v.IsNil() {
- v.Set(reflect.New(v.Type().Elem()))
- }
- v = v.Elem()
- }
- v = v.Field(i)
- }
- if v.Kind() == reflect.Ptr {
- if v.IsNil() {
- v.Set(reflect.New(v.Type().Elem()))
- }
- v = v.Elem()
- }
- }
- }
-
- // Check for unmarshaler on func field itself.
- u, ut, pv = d.indirect(v, false)
- if u != nil {
- d.off = nameStart
- err := u.UnmarshalJSON(d.next())
- if err != nil {
- d.error(err)
- }
- return
- }
-
- var mapElem reflect.Value
-
- // Parse function arguments.
- for i := 0; ; i++ {
- // closing ) - can only happen on first iteration.
- op := d.scanWhile(scanSkipSpace)
- if op == scanEndParams {
- break
- }
-
- // Back up so d.value can have the byte we just read.
- d.off--
- d.scan.undo(op)
-
- if i >= len(funcData.args) {
- d.error(fmt.Errorf("json: too many arguments for function %s", funcName))
- }
- key := []byte(funcData.args[i])
-
- // Figure out field corresponding to key.
- var subv reflect.Value
- destring := false // whether the value is wrapped in a string to be decoded first
-
- if v.Kind() == reflect.Map {
- elemType := v.Type().Elem()
- if !mapElem.IsValid() {
- mapElem = reflect.New(elemType).Elem()
- } else {
- mapElem.Set(reflect.Zero(elemType))
- }
- subv = mapElem
- } else {
- var f *field
- fields := cachedTypeFields(v.Type())
- for i := range fields {
- ff := &fields[i]
- if bytes.Equal(ff.nameBytes, key) {
- f = ff
- break
- }
- if f == nil && ff.equalFold(ff.nameBytes, key) {
- f = ff
- }
- }
- if f != nil {
- subv = v
- destring = f.quoted
- for _, i := range f.index {
- if subv.Kind() == reflect.Ptr {
- if subv.IsNil() {
- subv.Set(reflect.New(subv.Type().Elem()))
- }
- subv = subv.Elem()
- }
- subv = subv.Field(i)
- }
- }
- }
-
- // Read value.
- if destring {
- switch qv := d.valueQuoted().(type) {
- case nil:
- d.literalStore(nullLiteral, subv, false)
- case string:
- d.literalStore([]byte(qv), subv, true)
- default:
- d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal unquoted value into %v", subv.Type()))
- }
- } else {
- d.value(subv)
- }
-
- // Write value back to map;
- // if using struct, subv points into struct already.
- if v.Kind() == reflect.Map {
- kt := v.Type().Key()
- var kv reflect.Value
- switch {
- case kt.Kind() == reflect.String:
- kv = reflect.ValueOf(key).Convert(v.Type().Key())
- case reflect.PtrTo(kt).Implements(textUnmarshalerType):
- kv = reflect.New(v.Type().Key())
- d.literalStore(key, kv, true)
- kv = kv.Elem()
- default:
- panic("json: Unexpected key type") // should never occur
- }
- v.SetMapIndex(kv, subv)
- }
-
- // Next token must be , or ).
- op = d.scanWhile(scanSkipSpace)
- if op == scanEndParams {
- break
- }
- if op != scanParam {
- d.error(errPhase)
- }
- }
-}
-
-// keyed attempts to decode an object or function using a keyed doc extension,
-// and returns the value and true on success, or nil and false otherwise.
-func (d *decodeState) keyed() (interface{}, bool) {
- if len(d.ext.keyed) == 0 {
- return nil, false
- }
-
- unquote := false
-
- // Look-ahead first key to check for a keyed document extension.
- d.nextscan.reset()
- var start, end int
- for i, c := range d.data[d.off-1:] {
- switch op := d.nextscan.step(&d.nextscan, c); op {
- case scanSkipSpace, scanContinue, scanBeginObject:
- continue
- case scanBeginLiteral, scanBeginName:
- unquote = op == scanBeginLiteral
- start = i
- continue
- }
- end = i
- break
- }
-
- name := d.data[d.off-1+start : d.off-1+end]
-
- var key []byte
- var ok bool
- if unquote {
- key, ok = unquoteBytes(name)
- if !ok {
- d.error(errPhase)
- }
- } else {
- funcData, ok := d.ext.funcs[string(name)]
- if !ok {
- return nil, false
- }
- key = []byte(funcData.key)
- }
-
- decode, ok := d.ext.keyed[string(key)]
- if !ok {
- return nil, false
- }
-
- d.off--
- out, err := decode(d.next())
- if err != nil {
- d.error(err)
- }
- return out, true
-}
-
-func (d *decodeState) storeKeyed(v reflect.Value) bool {
- keyed, ok := d.keyed()
- if !ok {
- return false
- }
- d.storeValue(v, keyed)
- return true
-}
-
-var (
- trueBytes = []byte("true")
- falseBytes = []byte("false")
- nullBytes = []byte("null")
-)
-
-func (d *decodeState) storeValue(v reflect.Value, from interface{}) {
- switch from {
- case nil:
- d.literalStore(nullBytes, v, false)
- return
- case true:
- d.literalStore(trueBytes, v, false)
- return
- case false:
- d.literalStore(falseBytes, v, false)
- return
- }
- fromv := reflect.ValueOf(from)
- for fromv.Kind() == reflect.Ptr && !fromv.IsNil() {
- fromv = fromv.Elem()
- }
- fromt := fromv.Type()
- for v.Kind() == reflect.Ptr && !v.IsNil() {
- v = v.Elem()
- }
- vt := v.Type()
- if fromt.AssignableTo(vt) {
- v.Set(fromv)
- } else if fromt.ConvertibleTo(vt) {
- v.Set(fromv.Convert(vt))
- } else {
- d.saveError(&UnmarshalTypeError{"object", v.Type(), int64(d.off)})
- }
-}
-
-func (d *decodeState) convertLiteral(name []byte) (interface{}, bool) {
- if len(name) == 0 {
- return nil, false
- }
- switch name[0] {
- case 't':
- if bytes.Equal(name, trueBytes) {
- return true, true
- }
- case 'f':
- if bytes.Equal(name, falseBytes) {
- return false, true
- }
- case 'n':
- if bytes.Equal(name, nullBytes) {
- return nil, true
- }
- }
- if l, ok := d.ext.consts[string(name)]; ok {
- return l, true
- }
- return nil, false
-}
-
-// literal consumes a literal from d.data[d.off-1:], decoding into the value v.
-// The first byte of the literal has been read already
-// (that's how the caller knows it's a literal).
-func (d *decodeState) literal(v reflect.Value) {
- // All bytes inside literal return scanContinue op code.
- start := d.off - 1
- op := d.scanWhile(scanContinue)
-
- // Scan read one byte too far; back up.
- d.off--
- d.scan.undo(op)
-
- d.literalStore(d.data[start:d.off], v, false)
-}
-
-// convertNumber converts the number literal s to a float64 or a Number
-// depending on the setting of d.useNumber.
-func (d *decodeState) convertNumber(s string) (interface{}, error) {
- if d.useNumber {
- return Number(s), nil
- }
- f, err := strconv.ParseFloat(s, 64)
- if err != nil {
- return nil, &UnmarshalTypeError{"number " + s, reflect.TypeOf(0.0), int64(d.off)}
- }
- return f, nil
-}
-
-var numberType = reflect.TypeOf(Number(""))
-
-// literalStore decodes a literal stored in item into v.
-//
-// fromQuoted indicates whether this literal came from unwrapping a
-// string from the ",string" struct tag option. this is used only to
-// produce more helpful error messages.
-func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool) {
- // Check for unmarshaler.
- if len(item) == 0 {
- //Empty string given
- d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
- return
- }
- wantptr := item[0] == 'n' // null
- u, ut, pv := d.indirect(v, wantptr)
- if u != nil {
- err := u.UnmarshalJSON(item)
- if err != nil {
- d.error(err)
- }
- return
- }
- if ut != nil {
- if item[0] != '"' {
- if fromQuoted {
- d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
- } else {
- d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)})
- }
- return
- }
- s, ok := unquoteBytes(item)
- if !ok {
- if fromQuoted {
- d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
- } else {
- d.error(errPhase)
- }
- }
- err := ut.UnmarshalText(s)
- if err != nil {
- d.error(err)
- }
- return
- }
-
- v = pv
-
- switch c := item[0]; c {
- case 'n': // null
- switch v.Kind() {
- case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice:
- v.Set(reflect.Zero(v.Type()))
- // otherwise, ignore null for primitives/string
- }
- case 't', 'f': // true, false
- value := c == 't'
- switch v.Kind() {
- default:
- if fromQuoted {
- d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
- } else {
- d.saveError(&UnmarshalTypeError{"bool", v.Type(), int64(d.off)})
- }
- case reflect.Bool:
- v.SetBool(value)
- case reflect.Interface:
- if v.NumMethod() == 0 {
- v.Set(reflect.ValueOf(value))
- } else {
- d.saveError(&UnmarshalTypeError{"bool", v.Type(), int64(d.off)})
- }
- }
-
- case '"': // string
- s, ok := unquoteBytes(item)
- if !ok {
- if fromQuoted {
- d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
- } else {
- d.error(errPhase)
- }
- }
- switch v.Kind() {
- default:
- d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)})
- case reflect.Slice:
- if v.Type().Elem().Kind() != reflect.Uint8 {
- d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)})
- break
- }
- b := make([]byte, base64.StdEncoding.DecodedLen(len(s)))
- n, err := base64.StdEncoding.Decode(b, s)
- if err != nil {
- d.saveError(err)
- break
- }
- v.SetBytes(b[:n])
- case reflect.String:
- v.SetString(string(s))
- case reflect.Interface:
- if v.NumMethod() == 0 {
- v.Set(reflect.ValueOf(string(s)))
- } else {
- d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)})
- }
- }
-
- default: // number
- if c != '-' && (c < '0' || c > '9') {
- if fromQuoted {
- d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
- } else {
- d.error(errPhase)
- }
- }
- s := string(item)
- switch v.Kind() {
- default:
- if v.Kind() == reflect.String && v.Type() == numberType {
- v.SetString(s)
- if !isValidNumber(s) {
- d.error(fmt.Errorf("json: invalid number literal, trying to unmarshal %q into Number", item))
- }
- break
- }
- if fromQuoted {
- d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
- } else {
- d.error(&UnmarshalTypeError{"number", v.Type(), int64(d.off)})
- }
- case reflect.Interface:
- n, err := d.convertNumber(s)
- if err != nil {
- d.saveError(err)
- break
- }
- if v.NumMethod() != 0 {
- d.saveError(&UnmarshalTypeError{"number", v.Type(), int64(d.off)})
- break
- }
- v.Set(reflect.ValueOf(n))
-
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- n, err := strconv.ParseInt(s, 10, 64)
- if err != nil || v.OverflowInt(n) {
- d.saveError(&UnmarshalTypeError{"number " + s, v.Type(), int64(d.off)})
- break
- }
- v.SetInt(n)
-
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
- n, err := strconv.ParseUint(s, 10, 64)
- if err != nil || v.OverflowUint(n) {
- d.saveError(&UnmarshalTypeError{"number " + s, v.Type(), int64(d.off)})
- break
- }
- v.SetUint(n)
-
- case reflect.Float32, reflect.Float64:
- n, err := strconv.ParseFloat(s, v.Type().Bits())
- if err != nil || v.OverflowFloat(n) {
- d.saveError(&UnmarshalTypeError{"number " + s, v.Type(), int64(d.off)})
- break
- }
- v.SetFloat(n)
- }
- }
-}
-
-// The xxxInterface routines build up a value to be stored
-// in an empty interface. They are not strictly necessary,
-// but they avoid the weight of reflection in this common case.
-
-// valueInterface is like value but returns interface{}
-func (d *decodeState) valueInterface() interface{} {
- switch d.scanWhile(scanSkipSpace) {
- default:
- d.error(errPhase)
- panic("unreachable")
- case scanBeginArray:
- return d.arrayInterface()
- case scanBeginObject:
- return d.objectInterface()
- case scanBeginLiteral:
- return d.literalInterface()
- case scanBeginName:
- return d.nameInterface()
- }
-}
-
-func (d *decodeState) syntaxError(expected string) {
- msg := fmt.Sprintf("invalid character '%c' looking for %s", d.data[d.off-1], expected)
- d.error(&SyntaxError{msg, int64(d.off)})
-}
-
-// arrayInterface is like array but returns []interface{}.
-func (d *decodeState) arrayInterface() []interface{} {
- var v = make([]interface{}, 0)
- for {
- // Look ahead for ] - can only happen on first iteration.
- op := d.scanWhile(scanSkipSpace)
- if op == scanEndArray {
- if len(v) > 0 && !d.ext.trailingCommas {
- d.syntaxError("beginning of value")
- }
- break
- }
-
- // Back up so d.value can have the byte we just read.
- d.off--
- d.scan.undo(op)
-
- v = append(v, d.valueInterface())
-
- // Next token must be , or ].
- op = d.scanWhile(scanSkipSpace)
- if op == scanEndArray {
- break
- }
- if op != scanArrayValue {
- d.error(errPhase)
- }
- }
- return v
-}
-
-// objectInterface is like object but returns map[string]interface{}.
-func (d *decodeState) objectInterface() interface{} {
- v, ok := d.keyed()
- if ok {
- return v
- }
-
- m := make(map[string]interface{})
- for {
- // Read opening " of string key or closing }.
- op := d.scanWhile(scanSkipSpace)
- if op == scanEndObject {
- if len(m) > 0 && !d.ext.trailingCommas {
- d.syntaxError("beginning of object key string")
- }
- break
- }
- if op == scanBeginName {
- if !d.ext.unquotedKeys {
- d.syntaxError("beginning of object key string")
- }
- } else if op != scanBeginLiteral {
- d.error(errPhase)
- }
- unquotedKey := op == scanBeginName
-
- // Read string key.
- start := d.off - 1
- op = d.scanWhile(scanContinue)
- item := d.data[start : d.off-1]
- var key string
- if unquotedKey {
- key = string(item)
- } else {
- var ok bool
- key, ok = unquote(item)
- if !ok {
- d.error(errPhase)
- }
- }
-
- // Read : before value.
- if op == scanSkipSpace {
- op = d.scanWhile(scanSkipSpace)
- }
- if op != scanObjectKey {
- d.error(errPhase)
- }
-
- // Read value.
- m[key] = d.valueInterface()
-
- // Next token must be , or }.
- op = d.scanWhile(scanSkipSpace)
- if op == scanEndObject {
- break
- }
- if op != scanObjectValue {
- d.error(errPhase)
- }
- }
- return m
-}
-
-// literalInterface is like literal but returns an interface value.
-func (d *decodeState) literalInterface() interface{} {
- // All bytes inside literal return scanContinue op code.
- start := d.off - 1
- op := d.scanWhile(scanContinue)
-
- // Scan read one byte too far; back up.
- d.off--
- d.scan.undo(op)
- item := d.data[start:d.off]
-
- switch c := item[0]; c {
- case 'n': // null
- return nil
-
- case 't', 'f': // true, false
- return c == 't'
-
- case '"': // string
- s, ok := unquote(item)
- if !ok {
- d.error(errPhase)
- }
- return s
-
- default: // number
- if c != '-' && (c < '0' || c > '9') {
- d.error(errPhase)
- }
- n, err := d.convertNumber(string(item))
- if err != nil {
- d.saveError(err)
- }
- return n
- }
-}
-
-// nameInterface is like function but returns map[string]interface{}.
-func (d *decodeState) nameInterface() interface{} {
- v, ok := d.keyed()
- if ok {
- return v
- }
-
- nameStart := d.off - 1
-
- op := d.scanWhile(scanContinue)
-
- name := d.data[nameStart : d.off-1]
- if op != scanParam {
- // Back up so the byte just read is consumed next.
- d.off--
- d.scan.undo(op)
- if l, ok := d.convertLiteral(name); ok {
- return l
- }
- d.error(&SyntaxError{fmt.Sprintf("json: unknown constant %q", name), int64(d.off)})
- }
-
- funcName := string(name)
- funcData := d.ext.funcs[funcName]
- if funcData.key == "" {
- d.error(fmt.Errorf("json: unknown function %q", funcName))
- }
-
- m := make(map[string]interface{})
- for i := 0; ; i++ {
- // Look ahead for ) - can only happen on first iteration.
- op := d.scanWhile(scanSkipSpace)
- if op == scanEndParams {
- break
- }
-
- // Back up so d.value can have the byte we just read.
- d.off--
- d.scan.undo(op)
-
- if i >= len(funcData.args) {
- d.error(fmt.Errorf("json: too many arguments for function %s", funcName))
- }
- m[funcData.args[i]] = d.valueInterface()
-
- // Next token must be , or ).
- op = d.scanWhile(scanSkipSpace)
- if op == scanEndParams {
- break
- }
- if op != scanParam {
- d.error(errPhase)
- }
- }
- return map[string]interface{}{funcData.key: m}
-}
-
-// getu4 decodes \uXXXX from the beginning of s, returning the hex value,
-// or it returns -1.
-func getu4(s []byte) rune {
- if len(s) < 6 || s[0] != '\\' || s[1] != 'u' {
- return -1
- }
- r, err := strconv.ParseUint(string(s[2:6]), 16, 64)
- if err != nil {
- return -1
- }
- return rune(r)
-}
-
-// unquote converts a quoted JSON string literal s into an actual string t.
-// The rules are different than for Go, so cannot use strconv.Unquote.
-func unquote(s []byte) (t string, ok bool) {
- s, ok = unquoteBytes(s)
- t = string(s)
- return
-}
-
-func unquoteBytes(s []byte) (t []byte, ok bool) {
- if len(s) < 2 || s[0] != '"' || s[len(s)-1] != '"' {
- return
- }
- s = s[1 : len(s)-1]
-
- // Check for unusual characters. If there are none,
- // then no unquoting is needed, so return a slice of the
- // original bytes.
- r := 0
- for r < len(s) {
- c := s[r]
- if c == '\\' || c == '"' || c < ' ' {
- break
- }
- if c < utf8.RuneSelf {
- r++
- continue
- }
- rr, size := utf8.DecodeRune(s[r:])
- if rr == utf8.RuneError && size == 1 {
- break
- }
- r += size
- }
- if r == len(s) {
- return s, true
- }
-
- b := make([]byte, len(s)+2*utf8.UTFMax)
- w := copy(b, s[0:r])
- for r < len(s) {
- // Out of room? Can only happen if s is full of
- // malformed UTF-8 and we're replacing each
- // byte with RuneError.
- if w >= len(b)-2*utf8.UTFMax {
- nb := make([]byte, (len(b)+utf8.UTFMax)*2)
- copy(nb, b[0:w])
- b = nb
- }
- switch c := s[r]; {
- case c == '\\':
- r++
- if r >= len(s) {
- return
- }
- switch s[r] {
- default:
- return
- case '"', '\\', '/', '\'':
- b[w] = s[r]
- r++
- w++
- case 'b':
- b[w] = '\b'
- r++
- w++
- case 'f':
- b[w] = '\f'
- r++
- w++
- case 'n':
- b[w] = '\n'
- r++
- w++
- case 'r':
- b[w] = '\r'
- r++
- w++
- case 't':
- b[w] = '\t'
- r++
- w++
- case 'u':
- r--
- rr := getu4(s[r:])
- if rr < 0 {
- return
- }
- r += 6
- if utf16.IsSurrogate(rr) {
- rr1 := getu4(s[r:])
- if dec := utf16.DecodeRune(rr, rr1); dec != unicode.ReplacementChar {
- // A valid pair; consume.
- r += 6
- w += utf8.EncodeRune(b[w:], dec)
- break
- }
- // Invalid surrogate; fall back to replacement rune.
- rr = unicode.ReplacementChar
- }
- w += utf8.EncodeRune(b[w:], rr)
- }
-
- // Quote, control characters are invalid.
- case c == '"', c < ' ':
- return
-
- // ASCII
- case c < utf8.RuneSelf:
- b[w] = c
- r++
- w++
-
- // Coerce to well-formed UTF-8.
- default:
- rr, size := utf8.DecodeRune(s[r:])
- r += size
- w += utf8.EncodeRune(b[w:], rr)
- }
- }
- return b[0:w], true
-}
diff --git a/vendor/gopkg.in.o/mgo.v2/internal/json/decode_test.go b/vendor/gopkg.in.o/mgo.v2/internal/json/decode_test.go
deleted file mode 100644
index 30e46ca44..000000000
--- a/vendor/gopkg.in.o/mgo.v2/internal/json/decode_test.go
+++ /dev/null
@@ -1,1512 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package json
-
-import (
- "bytes"
- "encoding"
- "errors"
- "fmt"
- "image"
- "net"
- "reflect"
- "strings"
- "testing"
- "time"
-)
-
-type T struct {
- X string
- Y int
- Z int `json:"-"`
-}
-
-type U struct {
- Alphabet string `json:"alpha"`
-}
-
-type V struct {
- F1 interface{}
- F2 int32
- F3 Number
-}
-
-// ifaceNumAsFloat64/ifaceNumAsNumber are used to test unmarshaling with and
-// without UseNumber
-var ifaceNumAsFloat64 = map[string]interface{}{
- "k1": float64(1),
- "k2": "s",
- "k3": []interface{}{float64(1), float64(2.0), float64(3e-3)},
- "k4": map[string]interface{}{"kk1": "s", "kk2": float64(2)},
-}
-
-var ifaceNumAsNumber = map[string]interface{}{
- "k1": Number("1"),
- "k2": "s",
- "k3": []interface{}{Number("1"), Number("2.0"), Number("3e-3")},
- "k4": map[string]interface{}{"kk1": "s", "kk2": Number("2")},
-}
-
-type tx struct {
- x int
-}
-
-// A type that can unmarshal itself.
-
-type unmarshaler struct {
- T bool
-}
-
-func (u *unmarshaler) UnmarshalJSON(b []byte) error {
- *u = unmarshaler{true} // All we need to see that UnmarshalJSON is called.
- return nil
-}
-
-type ustruct struct {
- M unmarshaler
-}
-
-type unmarshalerText struct {
- A, B string
-}
-
-// needed for re-marshaling tests
-func (u unmarshalerText) MarshalText() ([]byte, error) {
- return []byte(u.A + ":" + u.B), nil
-}
-
-func (u *unmarshalerText) UnmarshalText(b []byte) error {
- pos := bytes.Index(b, []byte(":"))
- if pos == -1 {
- return errors.New("missing separator")
- }
- u.A, u.B = string(b[:pos]), string(b[pos+1:])
- return nil
-}
-
-var _ encoding.TextUnmarshaler = (*unmarshalerText)(nil)
-
-type ustructText struct {
- M unmarshalerText
-}
-
-var (
- um0, um1 unmarshaler // target2 of unmarshaling
- ump = &um1
- umtrue = unmarshaler{true}
- umslice = []unmarshaler{{true}}
- umslicep = new([]unmarshaler)
- umstruct = ustruct{unmarshaler{true}}
-
- um0T, um1T unmarshalerText // target2 of unmarshaling
- umpType = &um1T
- umtrueXY = unmarshalerText{"x", "y"}
- umsliceXY = []unmarshalerText{{"x", "y"}}
- umslicepType = new([]unmarshalerText)
- umstructType = new(ustructText)
- umstructXY = ustructText{unmarshalerText{"x", "y"}}
-
- ummapType = map[unmarshalerText]bool{}
- ummapXY = map[unmarshalerText]bool{unmarshalerText{"x", "y"}: true}
-)
-
-// Test data structures for anonymous fields.
-
-type Point struct {
- Z int
-}
-
-type Top struct {
- Level0 int
- Embed0
- *Embed0a
- *Embed0b `json:"e,omitempty"` // treated as named
- Embed0c `json:"-"` // ignored
- Loop
- Embed0p // has Point with X, Y, used
- Embed0q // has Point with Z, used
- embed // contains exported field
-}
-
-type Embed0 struct {
- Level1a int // overridden by Embed0a's Level1a with json tag
- Level1b int // used because Embed0a's Level1b is renamed
- Level1c int // used because Embed0a's Level1c is ignored
- Level1d int // annihilated by Embed0a's Level1d
- Level1e int `json:"x"` // annihilated by Embed0a.Level1e
-}
-
-type Embed0a struct {
- Level1a int `json:"Level1a,omitempty"`
- Level1b int `json:"LEVEL1B,omitempty"`
- Level1c int `json:"-"`
- Level1d int // annihilated by Embed0's Level1d
- Level1f int `json:"x"` // annihilated by Embed0's Level1e
-}
-
-type Embed0b Embed0
-
-type Embed0c Embed0
-
-type Embed0p struct {
- image.Point
-}
-
-type Embed0q struct {
- Point
-}
-
-type embed struct {
- Q int
-}
-
-type Loop struct {
- Loop1 int `json:",omitempty"`
- Loop2 int `json:",omitempty"`
- *Loop
-}
-
-// From reflect test:
-// The X in S6 and S7 annihilate, but they also block the X in S8.S9.
-type S5 struct {
- S6
- S7
- S8
-}
-
-type S6 struct {
- X int
-}
-
-type S7 S6
-
-type S8 struct {
- S9
-}
-
-type S9 struct {
- X int
- Y int
-}
-
-// From reflect test:
-// The X in S11.S6 and S12.S6 annihilate, but they also block the X in S13.S8.S9.
-type S10 struct {
- S11
- S12
- S13
-}
-
-type S11 struct {
- S6
-}
-
-type S12 struct {
- S6
-}
-
-type S13 struct {
- S8
-}
-
-type unmarshalTest struct {
- in string
- ptr interface{}
- out interface{}
- err error
- useNumber bool
-}
-
-type Ambig struct {
- // Given "hello", the first match should win.
- First int `json:"HELLO"`
- Second int `json:"Hello"`
-}
-
-type XYZ struct {
- X interface{}
- Y interface{}
- Z interface{}
-}
-
-func sliceAddr(x []int) *[]int { return &x }
-func mapAddr(x map[string]int) *map[string]int { return &x }
-
-var unmarshalTests = []unmarshalTest{
- // basic types
- {in: `true`, ptr: new(bool), out: true},
- {in: `1`, ptr: new(int), out: 1},
- {in: `1.2`, ptr: new(float64), out: 1.2},
- {in: `-5`, ptr: new(int16), out: int16(-5)},
- {in: `2`, ptr: new(Number), out: Number("2"), useNumber: true},
- {in: `2`, ptr: new(Number), out: Number("2")},
- {in: `2`, ptr: new(interface{}), out: float64(2.0)},
- {in: `2`, ptr: new(interface{}), out: Number("2"), useNumber: true},
- {in: `"a\u1234"`, ptr: new(string), out: "a\u1234"},
- {in: `"http:\/\/"`, ptr: new(string), out: "http://"},
- {in: `"g-clef: \uD834\uDD1E"`, ptr: new(string), out: "g-clef: \U0001D11E"},
- {in: `"invalid: \uD834x\uDD1E"`, ptr: new(string), out: "invalid: \uFFFDx\uFFFD"},
- {in: "null", ptr: new(interface{}), out: nil},
- {in: `{"X": [1,2,3], "Y": 4}`, ptr: new(T), out: T{Y: 4}, err: &UnmarshalTypeError{"array", reflect.TypeOf(""), 7}},
- {in: `{"x": 1}`, ptr: new(tx), out: tx{}},
- {in: `{"F1":1,"F2":2,"F3":3}`, ptr: new(V), out: V{F1: float64(1), F2: int32(2), F3: Number("3")}},
- {in: `{"F1":1,"F2":2,"F3":3}`, ptr: new(V), out: V{F1: Number("1"), F2: int32(2), F3: Number("3")}, useNumber: true},
- {in: `{"k1":1,"k2":"s","k3":[1,2.0,3e-3],"k4":{"kk1":"s","kk2":2}}`, ptr: new(interface{}), out: ifaceNumAsFloat64},
- {in: `{"k1":1,"k2":"s","k3":[1,2.0,3e-3],"k4":{"kk1":"s","kk2":2}}`, ptr: new(interface{}), out: ifaceNumAsNumber, useNumber: true},
-
- // raw values with whitespace
- {in: "\n true ", ptr: new(bool), out: true},
- {in: "\t 1 ", ptr: new(int), out: 1},
- {in: "\r 1.2 ", ptr: new(float64), out: 1.2},
- {in: "\t -5 \n", ptr: new(int16), out: int16(-5)},
- {in: "\t \"a\\u1234\" \n", ptr: new(string), out: "a\u1234"},
-
- // Z has a "-" tag.
- {in: `{"Y": 1, "Z": 2}`, ptr: new(T), out: T{Y: 1}},
-
- {in: `{"alpha": "abc", "alphabet": "xyz"}`, ptr: new(U), out: U{Alphabet: "abc"}},
- {in: `{"alpha": "abc"}`, ptr: new(U), out: U{Alphabet: "abc"}},
- {in: `{"alphabet": "xyz"}`, ptr: new(U), out: U{}},
-
- // syntax errors
- {in: `{"X": "foo", "Y"}`, err: &SyntaxError{"invalid character '}' after object key", 17}},
- {in: `[1, 2, 3+]`, err: &SyntaxError{"invalid character '+' after array element", 9}},
- {in: `{"X":12x}`, err: &SyntaxError{"invalid character 'x' after object key:value pair", 8}, useNumber: true},
-
- // raw value errors
- {in: "\x01 42", err: &SyntaxError{"invalid character '\\x01' looking for beginning of value", 1}},
- {in: " 42 \x01", err: &SyntaxError{"invalid character '\\x01' after top-level value", 5}},
- {in: "\x01 true", err: &SyntaxError{"invalid character '\\x01' looking for beginning of value", 1}},
- {in: " false \x01", err: &SyntaxError{"invalid character '\\x01' after top-level value", 8}},
- {in: "\x01 1.2", err: &SyntaxError{"invalid character '\\x01' looking for beginning of value", 1}},
- {in: " 3.4 \x01", err: &SyntaxError{"invalid character '\\x01' after top-level value", 6}},
- {in: "\x01 \"string\"", err: &SyntaxError{"invalid character '\\x01' looking for beginning of value", 1}},
- {in: " \"string\" \x01", err: &SyntaxError{"invalid character '\\x01' after top-level value", 11}},
-
- // array tests
- {in: `[1, 2, 3]`, ptr: new([3]int), out: [3]int{1, 2, 3}},
- {in: `[1, 2, 3]`, ptr: new([1]int), out: [1]int{1}},
- {in: `[1, 2, 3]`, ptr: new([5]int), out: [5]int{1, 2, 3, 0, 0}},
-
- // empty array to interface test
- {in: `[]`, ptr: new([]interface{}), out: []interface{}{}},
- {in: `null`, ptr: new([]interface{}), out: []interface{}(nil)},
- {in: `{"T":[]}`, ptr: new(map[string]interface{}), out: map[string]interface{}{"T": []interface{}{}}},
- {in: `{"T":null}`, ptr: new(map[string]interface{}), out: map[string]interface{}{"T": interface{}(nil)}},
-
- // composite tests
- {in: allValueIndent, ptr: new(All), out: allValue},
- {in: allValueCompact, ptr: new(All), out: allValue},
- {in: allValueIndent, ptr: new(*All), out: &allValue},
- {in: allValueCompact, ptr: new(*All), out: &allValue},
- {in: pallValueIndent, ptr: new(All), out: pallValue},
- {in: pallValueCompact, ptr: new(All), out: pallValue},
- {in: pallValueIndent, ptr: new(*All), out: &pallValue},
- {in: pallValueCompact, ptr: new(*All), out: &pallValue},
-
- // unmarshal interface test
- {in: `{"T":false}`, ptr: &um0, out: umtrue}, // use "false" so test will fail if custom unmarshaler is not called
- {in: `{"T":false}`, ptr: &ump, out: &umtrue},
- {in: `[{"T":false}]`, ptr: &umslice, out: umslice},
- {in: `[{"T":false}]`, ptr: &umslicep, out: &umslice},
- {in: `{"M":{"T":"x:y"}}`, ptr: &umstruct, out: umstruct},
-
- // UnmarshalText interface test
- {in: `"x:y"`, ptr: &um0T, out: umtrueXY},
- {in: `"x:y"`, ptr: &umpType, out: &umtrueXY},
- {in: `["x:y"]`, ptr: &umsliceXY, out: umsliceXY},
- {in: `["x:y"]`, ptr: &umslicepType, out: &umsliceXY},
- {in: `{"M":"x:y"}`, ptr: umstructType, out: umstructXY},
-
- // Map keys can be encoding.TextUnmarshalers
- {in: `{"x:y":true}`, ptr: &ummapType, out: ummapXY},
- // If multiple values for the same key exists, only the most recent value is used.
- {in: `{"x:y":false,"x:y":true}`, ptr: &ummapType, out: ummapXY},
-
- // Overwriting of data.
- // This is different from package xml, but it's what we've always done.
- // Now documented and tested.
- {in: `[2]`, ptr: sliceAddr([]int{1}), out: []int{2}},
- {in: `{"key": 2}`, ptr: mapAddr(map[string]int{"old": 0, "key": 1}), out: map[string]int{"key": 2}},
-
- {
- in: `{
- "Level0": 1,
- "Level1b": 2,
- "Level1c": 3,
- "x": 4,
- "Level1a": 5,
- "LEVEL1B": 6,
- "e": {
- "Level1a": 8,
- "Level1b": 9,
- "Level1c": 10,
- "Level1d": 11,
- "x": 12
- },
- "Loop1": 13,
- "Loop2": 14,
- "X": 15,
- "Y": 16,
- "Z": 17,
- "Q": 18
- }`,
- ptr: new(Top),
- out: Top{
- Level0: 1,
- Embed0: Embed0{
- Level1b: 2,
- Level1c: 3,
- },
- Embed0a: &Embed0a{
- Level1a: 5,
- Level1b: 6,
- },
- Embed0b: &Embed0b{
- Level1a: 8,
- Level1b: 9,
- Level1c: 10,
- Level1d: 11,
- Level1e: 12,
- },
- Loop: Loop{
- Loop1: 13,
- Loop2: 14,
- },
- Embed0p: Embed0p{
- Point: image.Point{X: 15, Y: 16},
- },
- Embed0q: Embed0q{
- Point: Point{Z: 17},
- },
- embed: embed{
- Q: 18,
- },
- },
- },
- {
- in: `{"hello": 1}`,
- ptr: new(Ambig),
- out: Ambig{First: 1},
- },
-
- {
- in: `{"X": 1,"Y":2}`,
- ptr: new(S5),
- out: S5{S8: S8{S9: S9{Y: 2}}},
- },
- {
- in: `{"X": 1,"Y":2}`,
- ptr: new(S10),
- out: S10{S13: S13{S8: S8{S9: S9{Y: 2}}}},
- },
-
- // invalid UTF-8 is coerced to valid UTF-8.
- {
- in: "\"hello\xffworld\"",
- ptr: new(string),
- out: "hello\ufffdworld",
- },
- {
- in: "\"hello\xc2\xc2world\"",
- ptr: new(string),
- out: "hello\ufffd\ufffdworld",
- },
- {
- in: "\"hello\xc2\xffworld\"",
- ptr: new(string),
- out: "hello\ufffd\ufffdworld",
- },
- {
- in: "\"hello\\ud800world\"",
- ptr: new(string),
- out: "hello\ufffdworld",
- },
- {
- in: "\"hello\\ud800\\ud800world\"",
- ptr: new(string),
- out: "hello\ufffd\ufffdworld",
- },
- {
- in: "\"hello\\ud800\\ud800world\"",
- ptr: new(string),
- out: "hello\ufffd\ufffdworld",
- },
- {
- in: "\"hello\xed\xa0\x80\xed\xb0\x80world\"",
- ptr: new(string),
- out: "hello\ufffd\ufffd\ufffd\ufffd\ufffd\ufffdworld",
- },
-
- // Used to be issue 8305, but time.Time implements encoding.TextUnmarshaler so this works now.
- {
- in: `{"2009-11-10T23:00:00Z": "hello world"}`,
- ptr: &map[time.Time]string{},
- out: map[time.Time]string{time.Date(2009, 11, 10, 23, 0, 0, 0, time.UTC): "hello world"},
- },
-
- // issue 8305
- {
- in: `{"2009-11-10T23:00:00Z": "hello world"}`,
- ptr: &map[Point]string{},
- err: &UnmarshalTypeError{"object", reflect.TypeOf(map[Point]string{}), 1},
- },
- {
- in: `{"asdf": "hello world"}`,
- ptr: &map[unmarshaler]string{},
- err: &UnmarshalTypeError{"object", reflect.TypeOf(map[unmarshaler]string{}), 1},
- },
-}
-
-func TestMarshal(t *testing.T) {
- b, err := Marshal(allValue)
- if err != nil {
- t.Fatalf("Marshal allValue: %v", err)
- }
- if string(b) != allValueCompact {
- t.Errorf("Marshal allValueCompact")
- diff(t, b, []byte(allValueCompact))
- return
- }
-
- b, err = Marshal(pallValue)
- if err != nil {
- t.Fatalf("Marshal pallValue: %v", err)
- }
- if string(b) != pallValueCompact {
- t.Errorf("Marshal pallValueCompact")
- diff(t, b, []byte(pallValueCompact))
- return
- }
-}
-
-var badUTF8 = []struct {
- in, out string
-}{
- {"hello\xffworld", `"hello\ufffdworld"`},
- {"", `""`},
- {"\xff", `"\ufffd"`},
- {"\xff\xff", `"\ufffd\ufffd"`},
- {"a\xffb", `"a\ufffdb"`},
- {"\xe6\x97\xa5\xe6\x9c\xac\xff\xaa\x9e", `"日本\ufffd\ufffd\ufffd"`},
-}
-
-func TestMarshalBadUTF8(t *testing.T) {
- for _, tt := range badUTF8 {
- b, err := Marshal(tt.in)
- if string(b) != tt.out || err != nil {
- t.Errorf("Marshal(%q) = %#q, %v, want %#q, nil", tt.in, b, err, tt.out)
- }
- }
-}
-
-func TestMarshalNumberZeroVal(t *testing.T) {
- var n Number
- out, err := Marshal(n)
- if err != nil {
- t.Fatal(err)
- }
- outStr := string(out)
- if outStr != "0" {
- t.Fatalf("Invalid zero val for Number: %q", outStr)
- }
-}
-
-func TestMarshalEmbeds(t *testing.T) {
- top := &Top{
- Level0: 1,
- Embed0: Embed0{
- Level1b: 2,
- Level1c: 3,
- },
- Embed0a: &Embed0a{
- Level1a: 5,
- Level1b: 6,
- },
- Embed0b: &Embed0b{
- Level1a: 8,
- Level1b: 9,
- Level1c: 10,
- Level1d: 11,
- Level1e: 12,
- },
- Loop: Loop{
- Loop1: 13,
- Loop2: 14,
- },
- Embed0p: Embed0p{
- Point: image.Point{X: 15, Y: 16},
- },
- Embed0q: Embed0q{
- Point: Point{Z: 17},
- },
- embed: embed{
- Q: 18,
- },
- }
- b, err := Marshal(top)
- if err != nil {
- t.Fatal(err)
- }
- want := "{\"Level0\":1,\"Level1b\":2,\"Level1c\":3,\"Level1a\":5,\"LEVEL1B\":6,\"e\":{\"Level1a\":8,\"Level1b\":9,\"Level1c\":10,\"Level1d\":11,\"x\":12},\"Loop1\":13,\"Loop2\":14,\"X\":15,\"Y\":16,\"Z\":17,\"Q\":18}"
- if string(b) != want {
- t.Errorf("Wrong marshal result.\n got: %q\nwant: %q", b, want)
- }
-}
-
-func TestUnmarshal(t *testing.T) {
- for i, tt := range unmarshalTests {
- var scan scanner
- in := []byte(tt.in)
- if err := checkValid(in, &scan); err != nil {
- if !reflect.DeepEqual(err, tt.err) {
- t.Errorf("#%d: checkValid: %#v", i, err)
- continue
- }
- }
- if tt.ptr == nil {
- continue
- }
-
- // v = new(right-type)
- v := reflect.New(reflect.TypeOf(tt.ptr).Elem())
- dec := NewDecoder(bytes.NewReader(in))
- if tt.useNumber {
- dec.UseNumber()
- }
- if err := dec.Decode(v.Interface()); !reflect.DeepEqual(err, tt.err) {
- t.Errorf("#%d: %v, want %v", i, err, tt.err)
- continue
- } else if err != nil {
- continue
- }
- if !reflect.DeepEqual(v.Elem().Interface(), tt.out) {
- t.Errorf("#%d: mismatch\nhave: %#+v\nwant: %#+v", i, v.Elem().Interface(), tt.out)
- data, _ := Marshal(v.Elem().Interface())
- println(string(data))
- data, _ = Marshal(tt.out)
- println(string(data))
- continue
- }
-
- // Check round trip.
- if tt.err == nil {
- enc, err := Marshal(v.Interface())
- if err != nil {
- t.Errorf("#%d: error re-marshaling: %v", i, err)
- continue
- }
- vv := reflect.New(reflect.TypeOf(tt.ptr).Elem())
- dec = NewDecoder(bytes.NewReader(enc))
- if tt.useNumber {
- dec.UseNumber()
- }
- if err := dec.Decode(vv.Interface()); err != nil {
- t.Errorf("#%d: error re-unmarshaling %#q: %v", i, enc, err)
- continue
- }
- if !reflect.DeepEqual(v.Elem().Interface(), vv.Elem().Interface()) {
- t.Errorf("#%d: mismatch\nhave: %#+v\nwant: %#+v", i, v.Elem().Interface(), vv.Elem().Interface())
- t.Errorf(" In: %q", strings.Map(noSpace, string(in)))
- t.Errorf("Marshal: %q", strings.Map(noSpace, string(enc)))
- continue
- }
- }
- }
-}
-
-func TestUnmarshalMarshal(t *testing.T) {
- initBig()
- var v interface{}
- if err := Unmarshal(jsonBig, &v); err != nil {
- t.Fatalf("Unmarshal: %v", err)
- }
- b, err := Marshal(v)
- if err != nil {
- t.Fatalf("Marshal: %v", err)
- }
- if !bytes.Equal(jsonBig, b) {
- t.Errorf("Marshal jsonBig")
- diff(t, b, jsonBig)
- return
- }
-}
-
-var numberTests = []struct {
- in string
- i int64
- intErr string
- f float64
- floatErr string
-}{
- {in: "-1.23e1", intErr: "strconv.ParseInt: parsing \"-1.23e1\": invalid syntax", f: -1.23e1},
- {in: "-12", i: -12, f: -12.0},
- {in: "1e1000", intErr: "strconv.ParseInt: parsing \"1e1000\": invalid syntax", floatErr: "strconv.ParseFloat: parsing \"1e1000\": value out of range"},
-}
-
-// Independent of Decode, basic coverage of the accessors in Number
-func TestNumberAccessors(t *testing.T) {
- for _, tt := range numberTests {
- n := Number(tt.in)
- if s := n.String(); s != tt.in {
- t.Errorf("Number(%q).String() is %q", tt.in, s)
- }
- if i, err := n.Int64(); err == nil && tt.intErr == "" && i != tt.i {
- t.Errorf("Number(%q).Int64() is %d", tt.in, i)
- } else if (err == nil && tt.intErr != "") || (err != nil && err.Error() != tt.intErr) {
- t.Errorf("Number(%q).Int64() wanted error %q but got: %v", tt.in, tt.intErr, err)
- }
- if f, err := n.Float64(); err == nil && tt.floatErr == "" && f != tt.f {
- t.Errorf("Number(%q).Float64() is %g", tt.in, f)
- } else if (err == nil && tt.floatErr != "") || (err != nil && err.Error() != tt.floatErr) {
- t.Errorf("Number(%q).Float64() wanted error %q but got: %v", tt.in, tt.floatErr, err)
- }
- }
-}
-
-func TestLargeByteSlice(t *testing.T) {
- s0 := make([]byte, 2000)
- for i := range s0 {
- s0[i] = byte(i)
- }
- b, err := Marshal(s0)
- if err != nil {
- t.Fatalf("Marshal: %v", err)
- }
- var s1 []byte
- if err := Unmarshal(b, &s1); err != nil {
- t.Fatalf("Unmarshal: %v", err)
- }
- if !bytes.Equal(s0, s1) {
- t.Errorf("Marshal large byte slice")
- diff(t, s0, s1)
- }
-}
-
-type Xint struct {
- X int
-}
-
-func TestUnmarshalInterface(t *testing.T) {
- var xint Xint
- var i interface{} = &xint
- if err := Unmarshal([]byte(`{"X":1}`), &i); err != nil {
- t.Fatalf("Unmarshal: %v", err)
- }
- if xint.X != 1 {
- t.Fatalf("Did not write to xint")
- }
-}
-
-func TestUnmarshalPtrPtr(t *testing.T) {
- var xint Xint
- pxint := &xint
- if err := Unmarshal([]byte(`{"X":1}`), &pxint); err != nil {
- t.Fatalf("Unmarshal: %v", err)
- }
- if xint.X != 1 {
- t.Fatalf("Did not write to xint")
- }
-}
-
-func TestEscape(t *testing.T) {
- const input = `"foobar"` + " [\u2028 \u2029]"
- const expected = `"\"foobar\"\u003chtml\u003e [\u2028 \u2029]"`
- b, err := Marshal(input)
- if err != nil {
- t.Fatalf("Marshal error: %v", err)
- }
- if s := string(b); s != expected {
- t.Errorf("Encoding of [%s]:\n got [%s]\nwant [%s]", input, s, expected)
- }
-}
-
-// WrongString is a struct that's misusing the ,string modifier.
-type WrongString struct {
- Message string `json:"result,string"`
-}
-
-type wrongStringTest struct {
- in, err string
-}
-
-var wrongStringTests = []wrongStringTest{
- {`{"result":"x"}`, `json: invalid use of ,string struct tag, trying to unmarshal "x" into string`},
- {`{"result":"foo"}`, `json: invalid use of ,string struct tag, trying to unmarshal "foo" into string`},
- {`{"result":"123"}`, `json: invalid use of ,string struct tag, trying to unmarshal "123" into string`},
- {`{"result":123}`, `json: invalid use of ,string struct tag, trying to unmarshal unquoted value into string`},
-}
-
-// If people misuse the ,string modifier, the error message should be
-// helpful, telling the user that they're doing it wrong.
-func TestErrorMessageFromMisusedString(t *testing.T) {
- for n, tt := range wrongStringTests {
- r := strings.NewReader(tt.in)
- var s WrongString
- err := NewDecoder(r).Decode(&s)
- got := fmt.Sprintf("%v", err)
- if got != tt.err {
- t.Errorf("%d. got err = %q, want %q", n, got, tt.err)
- }
- }
-}
-
-func noSpace(c rune) rune {
- if isSpace(byte(c)) { //only used for ascii
- return -1
- }
- return c
-}
-
-type All struct {
- Bool bool
- Int int
- Int8 int8
- Int16 int16
- Int32 int32
- Int64 int64
- Uint uint
- Uint8 uint8
- Uint16 uint16
- Uint32 uint32
- Uint64 uint64
- Uintptr uintptr
- Float32 float32
- Float64 float64
-
- Foo string `json:"bar"`
- Foo2 string `json:"bar2,dummyopt"`
-
- IntStr int64 `json:",string"`
-
- PBool *bool
- PInt *int
- PInt8 *int8
- PInt16 *int16
- PInt32 *int32
- PInt64 *int64
- PUint *uint
- PUint8 *uint8
- PUint16 *uint16
- PUint32 *uint32
- PUint64 *uint64
- PUintptr *uintptr
- PFloat32 *float32
- PFloat64 *float64
-
- String string
- PString *string
-
- Map map[string]Small
- MapP map[string]*Small
- PMap *map[string]Small
- PMapP *map[string]*Small
-
- EmptyMap map[string]Small
- NilMap map[string]Small
-
- Slice []Small
- SliceP []*Small
- PSlice *[]Small
- PSliceP *[]*Small
-
- EmptySlice []Small
- NilSlice []Small
-
- StringSlice []string
- ByteSlice []byte
-
- Small Small
- PSmall *Small
- PPSmall **Small
-
- Interface interface{}
- PInterface *interface{}
-
- unexported int
-}
-
-type Small struct {
- Tag string
-}
-
-var allValue = All{
- Bool: true,
- Int: 2,
- Int8: 3,
- Int16: 4,
- Int32: 5,
- Int64: 6,
- Uint: 7,
- Uint8: 8,
- Uint16: 9,
- Uint32: 10,
- Uint64: 11,
- Uintptr: 12,
- Float32: 14.1,
- Float64: 15.1,
- Foo: "foo",
- Foo2: "foo2",
- IntStr: 42,
- String: "16",
- Map: map[string]Small{
- "17": {Tag: "tag17"},
- "18": {Tag: "tag18"},
- },
- MapP: map[string]*Small{
- "19": {Tag: "tag19"},
- "20": nil,
- },
- EmptyMap: map[string]Small{},
- Slice: []Small{{Tag: "tag20"}, {Tag: "tag21"}},
- SliceP: []*Small{{Tag: "tag22"}, nil, {Tag: "tag23"}},
- EmptySlice: []Small{},
- StringSlice: []string{"str24", "str25", "str26"},
- ByteSlice: []byte{27, 28, 29},
- Small: Small{Tag: "tag30"},
- PSmall: &Small{Tag: "tag31"},
- Interface: 5.2,
-}
-
-var pallValue = All{
- PBool: &allValue.Bool,
- PInt: &allValue.Int,
- PInt8: &allValue.Int8,
- PInt16: &allValue.Int16,
- PInt32: &allValue.Int32,
- PInt64: &allValue.Int64,
- PUint: &allValue.Uint,
- PUint8: &allValue.Uint8,
- PUint16: &allValue.Uint16,
- PUint32: &allValue.Uint32,
- PUint64: &allValue.Uint64,
- PUintptr: &allValue.Uintptr,
- PFloat32: &allValue.Float32,
- PFloat64: &allValue.Float64,
- PString: &allValue.String,
- PMap: &allValue.Map,
- PMapP: &allValue.MapP,
- PSlice: &allValue.Slice,
- PSliceP: &allValue.SliceP,
- PPSmall: &allValue.PSmall,
- PInterface: &allValue.Interface,
-}
-
-var allValueIndent = `{
- "Bool": true,
- "Int": 2,
- "Int8": 3,
- "Int16": 4,
- "Int32": 5,
- "Int64": 6,
- "Uint": 7,
- "Uint8": 8,
- "Uint16": 9,
- "Uint32": 10,
- "Uint64": 11,
- "Uintptr": 12,
- "Float32": 14.1,
- "Float64": 15.1,
- "bar": "foo",
- "bar2": "foo2",
- "IntStr": "42",
- "PBool": null,
- "PInt": null,
- "PInt8": null,
- "PInt16": null,
- "PInt32": null,
- "PInt64": null,
- "PUint": null,
- "PUint8": null,
- "PUint16": null,
- "PUint32": null,
- "PUint64": null,
- "PUintptr": null,
- "PFloat32": null,
- "PFloat64": null,
- "String": "16",
- "PString": null,
- "Map": {
- "17": {
- "Tag": "tag17"
- },
- "18": {
- "Tag": "tag18"
- }
- },
- "MapP": {
- "19": {
- "Tag": "tag19"
- },
- "20": null
- },
- "PMap": null,
- "PMapP": null,
- "EmptyMap": {},
- "NilMap": null,
- "Slice": [
- {
- "Tag": "tag20"
- },
- {
- "Tag": "tag21"
- }
- ],
- "SliceP": [
- {
- "Tag": "tag22"
- },
- null,
- {
- "Tag": "tag23"
- }
- ],
- "PSlice": null,
- "PSliceP": null,
- "EmptySlice": [],
- "NilSlice": null,
- "StringSlice": [
- "str24",
- "str25",
- "str26"
- ],
- "ByteSlice": "Gxwd",
- "Small": {
- "Tag": "tag30"
- },
- "PSmall": {
- "Tag": "tag31"
- },
- "PPSmall": null,
- "Interface": 5.2,
- "PInterface": null
-}`
-
-var allValueCompact = strings.Map(noSpace, allValueIndent)
-
-var pallValueIndent = `{
- "Bool": false,
- "Int": 0,
- "Int8": 0,
- "Int16": 0,
- "Int32": 0,
- "Int64": 0,
- "Uint": 0,
- "Uint8": 0,
- "Uint16": 0,
- "Uint32": 0,
- "Uint64": 0,
- "Uintptr": 0,
- "Float32": 0,
- "Float64": 0,
- "bar": "",
- "bar2": "",
- "IntStr": "0",
- "PBool": true,
- "PInt": 2,
- "PInt8": 3,
- "PInt16": 4,
- "PInt32": 5,
- "PInt64": 6,
- "PUint": 7,
- "PUint8": 8,
- "PUint16": 9,
- "PUint32": 10,
- "PUint64": 11,
- "PUintptr": 12,
- "PFloat32": 14.1,
- "PFloat64": 15.1,
- "String": "",
- "PString": "16",
- "Map": null,
- "MapP": null,
- "PMap": {
- "17": {
- "Tag": "tag17"
- },
- "18": {
- "Tag": "tag18"
- }
- },
- "PMapP": {
- "19": {
- "Tag": "tag19"
- },
- "20": null
- },
- "EmptyMap": null,
- "NilMap": null,
- "Slice": null,
- "SliceP": null,
- "PSlice": [
- {
- "Tag": "tag20"
- },
- {
- "Tag": "tag21"
- }
- ],
- "PSliceP": [
- {
- "Tag": "tag22"
- },
- null,
- {
- "Tag": "tag23"
- }
- ],
- "EmptySlice": null,
- "NilSlice": null,
- "StringSlice": null,
- "ByteSlice": null,
- "Small": {
- "Tag": ""
- },
- "PSmall": null,
- "PPSmall": {
- "Tag": "tag31"
- },
- "Interface": null,
- "PInterface": 5.2
-}`
-
-var pallValueCompact = strings.Map(noSpace, pallValueIndent)
-
-func TestRefUnmarshal(t *testing.T) {
- type S struct {
- // Ref is defined in encode_test.go.
- R0 Ref
- R1 *Ref
- R2 RefText
- R3 *RefText
- }
- want := S{
- R0: 12,
- R1: new(Ref),
- R2: 13,
- R3: new(RefText),
- }
- *want.R1 = 12
- *want.R3 = 13
-
- var got S
- if err := Unmarshal([]byte(`{"R0":"ref","R1":"ref","R2":"ref","R3":"ref"}`), &got); err != nil {
- t.Fatalf("Unmarshal: %v", err)
- }
- if !reflect.DeepEqual(got, want) {
- t.Errorf("got %+v, want %+v", got, want)
- }
-}
-
-// Test that the empty string doesn't panic decoding when ,string is specified
-// Issue 3450
-func TestEmptyString(t *testing.T) {
- type T2 struct {
- Number1 int `json:",string"`
- Number2 int `json:",string"`
- }
- data := `{"Number1":"1", "Number2":""}`
- dec := NewDecoder(strings.NewReader(data))
- var t2 T2
- err := dec.Decode(&t2)
- if err == nil {
- t.Fatal("Decode: did not return error")
- }
- if t2.Number1 != 1 {
- t.Fatal("Decode: did not set Number1")
- }
-}
-
-// Test that a null for ,string is not replaced with the previous quoted string (issue 7046).
-// It should also not be an error (issue 2540, issue 8587).
-func TestNullString(t *testing.T) {
- type T struct {
- A int `json:",string"`
- B int `json:",string"`
- C *int `json:",string"`
- }
- data := []byte(`{"A": "1", "B": null, "C": null}`)
- var s T
- s.B = 1
- s.C = new(int)
- *s.C = 2
- err := Unmarshal(data, &s)
- if err != nil {
- t.Fatalf("Unmarshal: %v", err)
- }
- if s.B != 1 || s.C != nil {
- t.Fatalf("after Unmarshal, s.B=%d, s.C=%p, want 1, nil", s.B, s.C)
- }
-}
-
-func intp(x int) *int {
- p := new(int)
- *p = x
- return p
-}
-
-func intpp(x *int) **int {
- pp := new(*int)
- *pp = x
- return pp
-}
-
-var interfaceSetTests = []struct {
- pre interface{}
- json string
- post interface{}
-}{
- {"foo", `"bar"`, "bar"},
- {"foo", `2`, 2.0},
- {"foo", `true`, true},
- {"foo", `null`, nil},
-
- {nil, `null`, nil},
- {new(int), `null`, nil},
- {(*int)(nil), `null`, nil},
- {new(*int), `null`, new(*int)},
- {(**int)(nil), `null`, nil},
- {intp(1), `null`, nil},
- {intpp(nil), `null`, intpp(nil)},
- {intpp(intp(1)), `null`, intpp(nil)},
-}
-
-func TestInterfaceSet(t *testing.T) {
- for _, tt := range interfaceSetTests {
- b := struct{ X interface{} }{tt.pre}
- blob := `{"X":` + tt.json + `}`
- if err := Unmarshal([]byte(blob), &b); err != nil {
- t.Errorf("Unmarshal %#q: %v", blob, err)
- continue
- }
- if !reflect.DeepEqual(b.X, tt.post) {
- t.Errorf("Unmarshal %#q into %#v: X=%#v, want %#v", blob, tt.pre, b.X, tt.post)
- }
- }
-}
-
-// JSON null values should be ignored for primitives and string values instead of resulting in an error.
-// Issue 2540
-func TestUnmarshalNulls(t *testing.T) {
- jsonData := []byte(`{
- "Bool" : null,
- "Int" : null,
- "Int8" : null,
- "Int16" : null,
- "Int32" : null,
- "Int64" : null,
- "Uint" : null,
- "Uint8" : null,
- "Uint16" : null,
- "Uint32" : null,
- "Uint64" : null,
- "Float32" : null,
- "Float64" : null,
- "String" : null}`)
-
- nulls := All{
- Bool: true,
- Int: 2,
- Int8: 3,
- Int16: 4,
- Int32: 5,
- Int64: 6,
- Uint: 7,
- Uint8: 8,
- Uint16: 9,
- Uint32: 10,
- Uint64: 11,
- Float32: 12.1,
- Float64: 13.1,
- String: "14"}
-
- err := Unmarshal(jsonData, &nulls)
- if err != nil {
- t.Errorf("Unmarshal of null values failed: %v", err)
- }
- if !nulls.Bool || nulls.Int != 2 || nulls.Int8 != 3 || nulls.Int16 != 4 || nulls.Int32 != 5 || nulls.Int64 != 6 ||
- nulls.Uint != 7 || nulls.Uint8 != 8 || nulls.Uint16 != 9 || nulls.Uint32 != 10 || nulls.Uint64 != 11 ||
- nulls.Float32 != 12.1 || nulls.Float64 != 13.1 || nulls.String != "14" {
-
- t.Errorf("Unmarshal of null values affected primitives")
- }
-}
-
-func TestStringKind(t *testing.T) {
- type stringKind string
-
- var m1, m2 map[stringKind]int
- m1 = map[stringKind]int{
- "foo": 42,
- }
-
- data, err := Marshal(m1)
- if err != nil {
- t.Errorf("Unexpected error marshaling: %v", err)
- }
-
- err = Unmarshal(data, &m2)
- if err != nil {
- t.Errorf("Unexpected error unmarshaling: %v", err)
- }
-
- if !reflect.DeepEqual(m1, m2) {
- t.Error("Items should be equal after encoding and then decoding")
- }
-}
-
-// Custom types with []byte as underlying type could not be marshalled
-// and then unmarshalled.
-// Issue 8962.
-func TestByteKind(t *testing.T) {
- type byteKind []byte
-
- a := byteKind("hello")
-
- data, err := Marshal(a)
- if err != nil {
- t.Error(err)
- }
- var b byteKind
- err = Unmarshal(data, &b)
- if err != nil {
- t.Fatal(err)
- }
- if !reflect.DeepEqual(a, b) {
- t.Errorf("expected %v == %v", a, b)
- }
-}
-
-// The fix for issue 8962 introduced a regression.
-// Issue 12921.
-func TestSliceOfCustomByte(t *testing.T) {
- type Uint8 uint8
-
- a := []Uint8("hello")
-
- data, err := Marshal(a)
- if err != nil {
- t.Fatal(err)
- }
- var b []Uint8
- err = Unmarshal(data, &b)
- if err != nil {
- t.Fatal(err)
- }
- if !reflect.DeepEqual(a, b) {
- t.Fatalf("expected %v == %v", a, b)
- }
-}
-
-var decodeTypeErrorTests = []struct {
- dest interface{}
- src string
-}{
- {new(string), `{"user": "name"}`}, // issue 4628.
- {new(error), `{}`}, // issue 4222
- {new(error), `[]`},
- {new(error), `""`},
- {new(error), `123`},
- {new(error), `true`},
-}
-
-func TestUnmarshalTypeError(t *testing.T) {
- for _, item := range decodeTypeErrorTests {
- err := Unmarshal([]byte(item.src), item.dest)
- if _, ok := err.(*UnmarshalTypeError); !ok {
- t.Errorf("expected type error for Unmarshal(%q, type %T): got %T",
- item.src, item.dest, err)
- }
- }
-}
-
-var unmarshalSyntaxTests = []string{
- "tru",
- "fals",
- "nul",
- "123e",
- `"hello`,
- `[1,2,3`,
- `{"key":1`,
- `{"key":1,`,
-}
-
-func TestUnmarshalSyntax(t *testing.T) {
- var x interface{}
- for _, src := range unmarshalSyntaxTests {
- err := Unmarshal([]byte(src), &x)
- if _, ok := err.(*SyntaxError); !ok {
- t.Errorf("expected syntax error for Unmarshal(%q): got %T", src, err)
- }
- }
-}
-
-// Test handling of unexported fields that should be ignored.
-// Issue 4660
-type unexportedFields struct {
- Name string
- m map[string]interface{} `json:"-"`
- m2 map[string]interface{} `json:"abcd"`
-}
-
-func TestUnmarshalUnexported(t *testing.T) {
- input := `{"Name": "Bob", "m": {"x": 123}, "m2": {"y": 456}, "abcd": {"z": 789}}`
- want := &unexportedFields{Name: "Bob"}
-
- out := &unexportedFields{}
- err := Unmarshal([]byte(input), out)
- if err != nil {
- t.Errorf("got error %v, expected nil", err)
- }
- if !reflect.DeepEqual(out, want) {
- t.Errorf("got %q, want %q", out, want)
- }
-}
-
-// Time3339 is a time.Time which encodes to and from JSON
-// as an RFC 3339 time in UTC.
-type Time3339 time.Time
-
-func (t *Time3339) UnmarshalJSON(b []byte) error {
- if len(b) < 2 || b[0] != '"' || b[len(b)-1] != '"' {
- return fmt.Errorf("types: failed to unmarshal non-string value %q as an RFC 3339 time", b)
- }
- tm, err := time.Parse(time.RFC3339, string(b[1:len(b)-1]))
- if err != nil {
- return err
- }
- *t = Time3339(tm)
- return nil
-}
-
-func TestUnmarshalJSONLiteralError(t *testing.T) {
- var t3 Time3339
- err := Unmarshal([]byte(`"0000-00-00T00:00:00Z"`), &t3)
- if err == nil {
- t.Fatalf("expected error; got time %v", time.Time(t3))
- }
- if !strings.Contains(err.Error(), "range") {
- t.Errorf("got err = %v; want out of range error", err)
- }
-}
-
-// Test that extra object elements in an array do not result in a
-// "data changing underfoot" error.
-// Issue 3717
-func TestSkipArrayObjects(t *testing.T) {
- json := `[{}]`
- var dest [0]interface{}
-
- err := Unmarshal([]byte(json), &dest)
- if err != nil {
- t.Errorf("got error %q, want nil", err)
- }
-}
-
-// Test semantics of pre-filled struct fields and pre-filled map fields.
-// Issue 4900.
-func TestPrefilled(t *testing.T) {
- ptrToMap := func(m map[string]interface{}) *map[string]interface{} { return &m }
-
- // Values here change, cannot reuse table across runs.
- var prefillTests = []struct {
- in string
- ptr interface{}
- out interface{}
- }{
- {
- in: `{"X": 1, "Y": 2}`,
- ptr: &XYZ{X: float32(3), Y: int16(4), Z: 1.5},
- out: &XYZ{X: float64(1), Y: float64(2), Z: 1.5},
- },
- {
- in: `{"X": 1, "Y": 2}`,
- ptr: ptrToMap(map[string]interface{}{"X": float32(3), "Y": int16(4), "Z": 1.5}),
- out: ptrToMap(map[string]interface{}{"X": float64(1), "Y": float64(2), "Z": 1.5}),
- },
- }
-
- for _, tt := range prefillTests {
- ptrstr := fmt.Sprintf("%v", tt.ptr)
- err := Unmarshal([]byte(tt.in), tt.ptr) // tt.ptr edited here
- if err != nil {
- t.Errorf("Unmarshal: %v", err)
- }
- if !reflect.DeepEqual(tt.ptr, tt.out) {
- t.Errorf("Unmarshal(%#q, %s): have %v, want %v", tt.in, ptrstr, tt.ptr, tt.out)
- }
- }
-}
-
-var invalidUnmarshalTests = []struct {
- v interface{}
- want string
-}{
- {nil, "json: Unmarshal(nil)"},
- {struct{}{}, "json: Unmarshal(non-pointer struct {})"},
- {(*int)(nil), "json: Unmarshal(nil *int)"},
-}
-
-func TestInvalidUnmarshal(t *testing.T) {
- buf := []byte(`{"a":"1"}`)
- for _, tt := range invalidUnmarshalTests {
- err := Unmarshal(buf, tt.v)
- if err == nil {
- t.Errorf("Unmarshal expecting error, got nil")
- continue
- }
- if got := err.Error(); got != tt.want {
- t.Errorf("Unmarshal = %q; want %q", got, tt.want)
- }
- }
-}
-
-var invalidUnmarshalTextTests = []struct {
- v interface{}
- want string
-}{
- {nil, "json: Unmarshal(nil)"},
- {struct{}{}, "json: Unmarshal(non-pointer struct {})"},
- {(*int)(nil), "json: Unmarshal(nil *int)"},
- {new(net.IP), "json: cannot unmarshal string into Go value of type *net.IP"},
-}
-
-func TestInvalidUnmarshalText(t *testing.T) {
- buf := []byte(`123`)
- for _, tt := range invalidUnmarshalTextTests {
- err := Unmarshal(buf, tt.v)
- if err == nil {
- t.Errorf("Unmarshal expecting error, got nil")
- continue
- }
- if got := err.Error(); got != tt.want {
- t.Errorf("Unmarshal = %q; want %q", got, tt.want)
- }
- }
-}
-
-// Test that string option is ignored for invalid types.
-// Issue 9812.
-func TestInvalidStringOption(t *testing.T) {
- num := 0
- item := struct {
- T time.Time `json:",string"`
- M map[string]string `json:",string"`
- S []string `json:",string"`
- A [1]string `json:",string"`
- I interface{} `json:",string"`
- P *int `json:",string"`
- }{M: make(map[string]string), S: make([]string, 0), I: num, P: &num}
-
- data, err := Marshal(item)
- if err != nil {
- t.Fatalf("Marshal: %v", err)
- }
-
- err = Unmarshal(data, &item)
- if err != nil {
- t.Fatalf("Unmarshal: %v", err)
- }
-}
diff --git a/vendor/gopkg.in.o/mgo.v2/internal/json/encode.go b/vendor/gopkg.in.o/mgo.v2/internal/json/encode.go
deleted file mode 100644
index 67a0f0062..000000000
--- a/vendor/gopkg.in.o/mgo.v2/internal/json/encode.go
+++ /dev/null
@@ -1,1256 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package json implements encoding and decoding of JSON as defined in
-// RFC 4627. The mapping between JSON and Go values is described
-// in the documentation for the Marshal and Unmarshal functions.
-//
-// See "JSON and Go" for an introduction to this package:
-// https://golang.org/doc/articles/json_and_go.html
-package json
-
-import (
- "bytes"
- "encoding"
- "encoding/base64"
- "fmt"
- "math"
- "reflect"
- "runtime"
- "sort"
- "strconv"
- "strings"
- "sync"
- "unicode"
- "unicode/utf8"
-)
-
-// Marshal returns the JSON encoding of v.
-//
-// Marshal traverses the value v recursively.
-// If an encountered value implements the Marshaler interface
-// and is not a nil pointer, Marshal calls its MarshalJSON method
-// to produce JSON. If no MarshalJSON method is present but the
-// value implements encoding.TextMarshaler instead, Marshal calls
-// its MarshalText method.
-// The nil pointer exception is not strictly necessary
-// but mimics a similar, necessary exception in the behavior of
-// UnmarshalJSON.
-//
-// Otherwise, Marshal uses the following type-dependent default encodings:
-//
-// Boolean values encode as JSON booleans.
-//
-// Floating point, integer, and Number values encode as JSON numbers.
-//
-// String values encode as JSON strings coerced to valid UTF-8,
-// replacing invalid bytes with the Unicode replacement rune.
-// The angle brackets "<" and ">" are escaped to "\u003c" and "\u003e"
-// to keep some browsers from misinterpreting JSON output as HTML.
-// Ampersand "&" is also escaped to "\u0026" for the same reason.
-// This escaping can be disabled using an Encoder with DisableHTMLEscaping.
-//
-// Array and slice values encode as JSON arrays, except that
-// []byte encodes as a base64-encoded string, and a nil slice
-// encodes as the null JSON value.
-//
-// Struct values encode as JSON objects. Each exported struct field
-// becomes a member of the object unless
-// - the field's tag is "-", or
-// - the field is empty and its tag specifies the "omitempty" option.
-// The empty values are false, 0, any
-// nil pointer or interface value, and any array, slice, map, or string of
-// length zero. The object's default key string is the struct field name
-// but can be specified in the struct field's tag value. The "json" key in
-// the struct field's tag value is the key name, followed by an optional comma
-// and options. Examples:
-//
-// // Field is ignored by this package.
-// Field int `json:"-"`
-//
-// // Field appears in JSON as key "myName".
-// Field int `json:"myName"`
-//
-// // Field appears in JSON as key "myName" and
-// // the field is omitted from the object if its value is empty,
-// // as defined above.
-// Field int `json:"myName,omitempty"`
-//
-// // Field appears in JSON as key "Field" (the default), but
-// // the field is skipped if empty.
-// // Note the leading comma.
-// Field int `json:",omitempty"`
-//
-// The "string" option signals that a field is stored as JSON inside a
-// JSON-encoded string. It applies only to fields of string, floating point,
-// integer, or boolean types. This extra level of encoding is sometimes used
-// when communicating with JavaScript programs:
-//
-// Int64String int64 `json:",string"`
-//
-// The key name will be used if it's a non-empty string consisting of
-// only Unicode letters, digits, dollar signs, percent signs, hyphens,
-// underscores and slashes.
-//
-// Anonymous struct fields are usually marshaled as if their inner exported fields
-// were fields in the outer struct, subject to the usual Go visibility rules amended
-// as described in the next paragraph.
-// An anonymous struct field with a name given in its JSON tag is treated as
-// having that name, rather than being anonymous.
-// An anonymous struct field of interface type is treated the same as having
-// that type as its name, rather than being anonymous.
-//
-// The Go visibility rules for struct fields are amended for JSON when
-// deciding which field to marshal or unmarshal. If there are
-// multiple fields at the same level, and that level is the least
-// nested (and would therefore be the nesting level selected by the
-// usual Go rules), the following extra rules apply:
-//
-// 1) Of those fields, if any are JSON-tagged, only tagged fields are considered,
-// even if there are multiple untagged fields that would otherwise conflict.
-// 2) If there is exactly one field (tagged or not according to the first rule), that is selected.
-// 3) Otherwise there are multiple fields, and all are ignored; no error occurs.
-//
-// Handling of anonymous struct fields is new in Go 1.1.
-// Prior to Go 1.1, anonymous struct fields were ignored. To force ignoring of
-// an anonymous struct field in both current and earlier versions, give the field
-// a JSON tag of "-".
-//
-// Map values encode as JSON objects. The map's key type must either be a string
-// or implement encoding.TextMarshaler. The map keys are used as JSON object
-// keys, subject to the UTF-8 coercion described for string values above.
-//
-// Pointer values encode as the value pointed to.
-// A nil pointer encodes as the null JSON value.
-//
-// Interface values encode as the value contained in the interface.
-// A nil interface value encodes as the null JSON value.
-//
-// Channel, complex, and function values cannot be encoded in JSON.
-// Attempting to encode such a value causes Marshal to return
-// an UnsupportedTypeError.
-//
-// JSON cannot represent cyclic data structures and Marshal does not
-// handle them. Passing cyclic structures to Marshal will result in
-// an infinite recursion.
-//
-func Marshal(v interface{}) ([]byte, error) {
- e := &encodeState{}
- err := e.marshal(v, encOpts{escapeHTML: true})
- if err != nil {
- return nil, err
- }
- return e.Bytes(), nil
-}
-
-// MarshalIndent is like Marshal but applies Indent to format the output.
-func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) {
- b, err := Marshal(v)
- if err != nil {
- return nil, err
- }
- var buf bytes.Buffer
- err = Indent(&buf, b, prefix, indent)
- if err != nil {
- return nil, err
- }
- return buf.Bytes(), nil
-}
-
-// HTMLEscape appends to dst the JSON-encoded src with <, >, &, U+2028 and U+2029
-// characters inside string literals changed to \u003c, \u003e, \u0026, \u2028, \u2029
-// so that the JSON will be safe to embed inside HTML