feat: Waku v2 bridge

Issue #12610
This commit is contained in:
Michal Iskierko
2023-11-12 13:29:38 +01:00
parent 56e7bd01ca
commit 6d31343205
6716 changed files with 1982502 additions and 5891 deletions

2
vendor/github.com/russolsen/transit/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,2 @@
transit
pkg

202
vendor/github.com/russolsen/transit/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,202 @@
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.

124
vendor/github.com/russolsen/transit/README.md generated vendored Normal file
View File

@@ -0,0 +1,124 @@
# transit (go)
[![GoDoc](https://godoc.org/github.com/russolsen/transit?status.svg)](https://godoc.org/github.com/russolsen/transit)
Transit is a data format and a set of libraries for conveying values between applications written in different languages. This library provides support for marshalling Transit data to/from Go.
* [Rationale](http://blog.cognitect.com/blog/2014/7/22/transit)
* [Specification](http://github.com/cognitect/transit-format)
This implementation's major.minor version number corresponds to the version of the Transit specification it supports.
Currently on the JSON formats are implemented.
MessagePack is **not** implemented yet.
_NOTE: Transit is a work in progress and may evolve based on feedback. As a result, while Transit is a great option for transferring data between applications, it should not yet be used for storing data durably over time. This recommendation will change when the specification is complete._
## Usage
Reading data with Transit(go) involves creating a `transit.Decoder` and calling `Decode`:
```go
package main
import (
"fmt"
"os"
"github.com/russolsen/transit"
)
func ReadTransit(path string) interface{} {
f, err := os.Open(path)
if err != nil {
fmt.Printf("Error opening file: %v\n", err)
return nil
}
decoder := transit.NewDecoder(f)
value, err := decoder.Decode()
if err != nil {
fmt.Printf("Error reading Transit data: %v\n", err)
return nil
}
fmt.Printf("The value read is: %v\n", value)
return value
}
```
Writing is similar:
```go
func WriteTransit(path string, value interface{}) {
f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0777)
if err != nil {
fmt.Printf("Error opening file: %v\n", err)
return
}
encoder := transit.NewEncoder(f, false)
err = encoder.Encode(value)
if err != nil {
fmt.Printf("Error writing Transit data: %v\n", err)
return
}
}
```
## Default Type Mapping
| Semantic Type | write accepts | read produces |
|:--------------|:--------------|:--------------|
| null| nil | nil |
| string| string | string |
| boolean | bool| bool |
| integer, signed 64 bit| any signed or unsiged int type | int64 |
| floating pt decimal| float32 or float64 | float64 |
| bytes| []byte | []byte |
| keyword | transit.Keyword | transit.Keyword |
| symbol | transit.Symbol | transit.Keyword
| arbitrary precision decimal| big.Float or github.com/shopspring/decimal.Decimal| github.com/shopspring/decimal.Decimal |
| arbitrary precision integer| big.Int | big.Int |
| point in time | time.Time | time.Time |
| point in time RFC 33339 | - | time.Time |
| u| github.com/pborman/uuid UUID| github.com/pborman/uuid UUID|
| uri | net/url URL | net/url URL |
| char | rune | rune |
| special numbers | As defined by math NaN and math.Inf() | TBD
| array | arrays or slices | []interface{} |
| map | map[interface{}]interface{} | map[interface{}]interface{} |
| set | transit.Set | transit.Set |
| list | container/list List | container/list List |
| map w/ composite keys | transit.CMap | transit.CMap |
| link | transit.Link | transit.Link |
| ratio | big.Rat | big.Rat |
## Copyright and License
Copyright © 2016 Russ Olsen
This library is a Go port of the Java version created and maintained by Cognitect, therefore
Copyright © 2014 Cognitect
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.
This README file is based on the README from transit-csharp, therefore:
Copyright © 2014 NForza.
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.

90
vendor/github.com/russolsen/transit/cmap.go generated vendored Normal file
View File

@@ -0,0 +1,90 @@
// Copyright 2016 Russ Olsen. All Rights Reserved.
//
// This code is a Go port of the Java version created and maintained by Cognitect, therefore:
//
// Copyright 2014 Cognitect. All Rights Reserved.
//
// 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 transit
type CMapEntry struct {
Key interface{}
Value interface{}
}
func NewCMapEntry(key, value interface{}) *CMapEntry {
return &CMapEntry{Key: key, Value: value}
}
// CMap is used to hold maps that have composite keys (i.e. #cmap values).
// Since Go arrays and maps cannot be used as map keys, a CMap is represented
// here as a simple array of key/value entrys.
type CMap struct {
Entries []CMapEntry
}
func NewCMap() *CMap {
return &CMap{}
}
// FindBy searches thru the map, calling mf on each key in turn
// and returns the first entry for which mf evaluates to true.
func (cm CMap) FindBy(key interface{}, mf MatchF) *CMapEntry {
for _, entry := range cm.Entries {
if mf(key, entry.Key) {
return &entry
}
}
return nil
}
// Find a given key in the map and return it's corresponding value.
// The search thru the keys is done with ==, so the keys in the map
// must be comparable.
func (cm CMap) Index(keyValue interface{}) interface{} {
entry := cm.FindBy(keyValue, Equals)
if entry == nil {
return nil
}
return entry.Value
}
func (cm CMap) Put(key, value interface{}, mf MatchF) *CMap {
entry := cm.FindBy(key, mf)
if entry != nil {
entry.Value = value
} else {
entry = NewCMapEntry(key, value)
cm.Entries = append(cm.Entries, *entry)
}
return &cm
}
// Append inserts a new key/value pair w/o paying attention to
// duplicate keys.
func (cm *CMap) Append(key, value interface{}) *CMap {
entry := NewCMapEntry(key, value)
cm.Entries = append(cm.Entries, *entry)
return cm
}
// Size returns the number of key/value pairs.
func (cm *CMap) Size() int {
return len(cm.Entries)
}

33
vendor/github.com/russolsen/transit/const.go generated vendored Normal file
View File

@@ -0,0 +1,33 @@
// Copyright 2016 Russ Olsen. All Rights Reserved.
//
// This code is a Go port of the Java version created and maintained by Cognitect, therefore:
//
// Copyright 2014 Cognitect. All Rights Reserved.
//
// 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 transit
const start = "~"
const reserved = "`"
const sub = "^"
const escapeTag = "~~"
const escapeSub = "~^"
const escapeRes = "~`"
const startTag = "~#"
const startSym = "~$"
const startKW = "~:"
const mapAsArray = "^ "

322
vendor/github.com/russolsen/transit/decode.go generated vendored Normal file
View File

@@ -0,0 +1,322 @@
// Copyright 2016 Russ Olsen. All Rights Reserved.
//
// This code is a Go port of the Java version created and maintained by Cognitect, therefore:
//
// Copyright 2014 Cognitect. All Rights Reserved.
//
// 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 transit
import (
"encoding/json"
"io"
"strings"
)
type Handler func(Decoder, interface{}) (interface{}, error)
type Decoder struct {
jsd *json.Decoder
decoders map[string]Handler
cache *RollingCache
}
// NewDecoder returns a new Decoder, ready to read from r.
func NewDecoder(r io.Reader) *Decoder {
jsd := json.NewDecoder(r)
return NewJsonDecoder(jsd)
}
// NewDecoder returns a new Decoder, ready to read from jsr.
func NewJsonDecoder(jsd *json.Decoder) *Decoder {
jsd.UseNumber()
decoders := make(map[string]Handler)
d := Decoder{jsd: jsd, decoders: decoders, cache: NewRollingCache()}
initHandlers(&d)
return &d
}
func initHandlers(d *Decoder) {
d.AddHandler("_", DecodeNil)
d.AddHandler(":", DecodeKeyword)
d.AddHandler("?", DecodeBoolean)
d.AddHandler("b", DecodeByte)
d.AddHandler("d", DecodeFloat)
d.AddHandler("i", DecodeInteger)
d.AddHandler("n", DecodeBigInteger)
d.AddHandler("f", DecodeDecimal)
d.AddHandler("c", DecodeRune)
d.AddHandler("$", DecodeSymbol)
d.AddHandler("t", DecodeRFC3339)
d.AddHandler("m", DecodeTime)
d.AddHandler("u", DecodeUUID)
d.AddHandler("r", DecodeURI)
d.AddHandler("'", DecodeQuote)
d.AddHandler("z", DecodeSpecialNumber)
d.AddHandler("set", DecodeSet)
d.AddHandler("link", DecodeLink)
d.AddHandler("list", DecodeList)
d.AddHandler("cmap", DecodeCMap)
d.AddHandler("ratio", DecodeRatio)
d.AddHandler("unknown", DecodeIdentity)
}
// AddHandler adds a new handler to the decoder, allowing you to extend the types it can handle.
func (d Decoder) AddHandler(tag string, valueDecoder Handler) {
d.decoders[tag] = valueDecoder
}
func (d Decoder) parseString(s string) (interface{}, error) {
if d.cache.HasKey(s) {
return d.Parse(d.cache.Read(s), false)
} else if !strings.HasPrefix(s, start) {
return s, nil
} else if strings.HasPrefix(s, startTag) {
return TagId(s[2:]), nil
} else if vd := d.decoders[s[1:2]]; vd != nil {
return vd(d, s[2:])
} else if strings.HasPrefix(s, escapeTag) ||
strings.HasPrefix(s, escapeSub) ||
strings.HasPrefix(s, escapeRes) {
return s[1:], nil
} else {
tv := TaggedValue{TagId(s[1:2]), s[2:]}
return d.decoders["unknown"](d, tv)
}
}
func (d Decoder) parseSingleEntryMap(m map[string]interface{}) (interface{}, error) {
// The loop here is just a convenient way to get at the only
// entry in the map.
for k, v := range m {
key, err := d.Parse(k, true)
if err != nil {
return nil, err
}
value, err := d.Parse(v, true)
if err != nil {
return nil, err
}
if tag, isTag := key.(TagId); isTag {
tv := TaggedValue{Tag: tag, Value: value}
valueDecoder := d.DecoderFor(tag)
return valueDecoder(d, tv)
} else {
return map[interface{}]interface{}{key: value}, nil
}
}
return nil, nil // Should never get here
}
func (d Decoder) parseMultiEntryMap(m map[string]interface{}) (interface{}, error) {
var result = make(map[interface{}]interface{})
for k, v := range m {
key, err := d.Parse(k, true)
if err != nil {
return nil, err
}
value, err := d.Parse(v, false)
if err != nil {
return nil, err
}
result[key] = value
}
return result, nil
}
func (d Decoder) parseMap(m map[string]interface{}) (interface{}, error) {
if len(m) != 1 {
return d.parseMultiEntryMap(m)
} else {
return d.parseSingleEntryMap(m)
}
}
func (d Decoder) parseNormalArray(x []interface{}) (interface{}, error) {
var result = make([]interface{}, len(x))
for i, v := range x {
var err error
result[i], err = d.Parse(v, false)
if err != nil {
return nil, err
}
}
return result, nil
}
func (d Decoder) parseCMap(x []interface{}) (interface{}, error) {
var result = NewCMap()
l := len(x)
for i := 1; i < l; i += 2 {
key, err := d.Parse(x[i], true)
if err != nil {
return nil, err
}
value, err := d.Parse(x[i+1], false)
if err != nil {
return nil, err
}
result.Append(key, value)
}
return result, nil
}
func (d Decoder) parseArrayMap(x []interface{}) (interface{}, error) {
result := make(map[interface{}]interface{})
l := len(x)
for i := 1; i < l; i += 2 {
key, err := d.Parse(x[i], true)
if err != nil {
return nil, err
}
value, err := d.Parse(x[i+1], false)
if err != nil {
return nil, err
}
result[key] = value
}
return result, nil
}
func (d Decoder) DecoderFor(tagid TagId) Handler {
key := string(tagid)
handler := d.decoders[key]
if handler == nil {
handler = d.decoders["unknown"]
}
return handler
}
func (d Decoder) parseArray(x []interface{}) (interface{}, error) {
if len(x) == 0 {
return x, nil
}
e0, err := d.Parse(x[0], false)
if err != nil {
return nil, err
}
if e0 == mapAsArray {
return d.parseArrayMap(x)
}
if tagId, isTag := e0.(TagId); isTag {
var value interface{}
if value, err = d.Parse(x[1], false); err != nil {
return nil, err
}
tv := TaggedValue{Tag: tagId, Value: value}
valueDecoder := d.DecoderFor(tagId)
return valueDecoder(d, tv)
}
return d.parseNormalArray(x)
}
func (d Decoder) parseNumber(x json.Number) (interface{}, error) {
var s = x.String()
var err error
var result interface{}
if strings.ContainsAny(s, ".Ee") {
result, err = x.Float64()
} else {
result, err = x.Int64()
}
return result, err
}
func (d Decoder) Parse(x interface{}, asKey bool) (interface{}, error) {
switch v := x.(type) {
default:
return nil, &TransitError{Message: "Unexpected type"}
case nil:
return v, nil
case bool:
return v, nil
case json.Number:
return d.parseNumber(v)
case string:
result, err := d.parseString(v)
if err == nil && d.cache.IsCacheable(v, asKey) {
d.cache.Write(v)
}
return result, err
case map[string]interface{}:
return d.parseMap(v)
case []interface{}:
return d.parseArray(v)
}
}
// Decode decodes the next Transit value from the stream.
func (d Decoder) Decode() (interface{}, error) {
var jsonObject interface{}
var err = d.jsd.Decode(&jsonObject)
if err != nil {
return nil, err
} else {
return d.Parse(jsonObject, false)
}
}
// DecodeFromString is a handly function that decodes Transit data held in a string.
func DecodeFromString(s string) (interface{}, error) {
reader := strings.NewReader(s)
decoder := NewDecoder(reader)
return decoder.Decode()
}

152
vendor/github.com/russolsen/transit/emitter.go generated vendored Normal file
View File

@@ -0,0 +1,152 @@
// Copyright 2016 Russ Olsen. All Rights Reserved.
//
// This code is a Go port of the Java version created and maintained by Cognitect, therefore:
//
// Copyright 2014 Cognitect. All Rights Reserved.
//
// 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 transit
import (
"encoding/json"
"fmt"
"io"
"strings"
)
type DataEmitter interface {
Emit(s string) error
EmitString(s string, cacheable bool) error
EmitTag(s string) error
EmitInt(i int64, asKey bool) error
EmitFloat(f float64, asKey bool) error
EmitNil(asKey bool) error
EmitBool(bool, asKey bool) error
EmitStartArray() error
EmitArraySeparator() error
EmitEndArray() error
EmitStartMap() error
EmitMapSeparator() error
EmitKeySeparator() error
EmitEndMap() error
}
type JsonEmitter struct {
writer io.Writer
cache Cache
}
func NewJsonEmitter(w io.Writer, cache Cache) *JsonEmitter {
return &JsonEmitter{writer: w, cache: cache}
}
// Emit the string unaltered and without quotes. This is the lowest level emitter.
func (je JsonEmitter) Emit(s string) error {
_, err := je.writer.Write([]byte(s))
return err
}
// EmitBase emits the basic value supplied, encoding it as JSON.
func (je JsonEmitter) EmitBase(x interface{}) error {
bytes, err := json.Marshal(x)
if err == nil {
_, err = je.writer.Write(bytes)
}
return err
}
// EmitsTag emits a transit #tag. The string supplied should not include the '#'.
func (je JsonEmitter) EmitTag(s string) error {
return je.EmitString("~#"+s, true)
}
func (je JsonEmitter) EmitString(s string, cacheable bool) error {
if je.cache.IsCacheable(s, cacheable) {
s = je.cache.Write(s)
}
return je.EmitBase(s)
}
const MaxJsonInt = 1<<53 - 1
func (je JsonEmitter) EmitInt(i int64, asKey bool) error {
if asKey || (i > MaxJsonInt) {
return je.EmitString(fmt.Sprintf("~i%d", i), asKey)
}
return je.EmitBase(i)
}
func (je JsonEmitter) EmitNil(asKey bool) error {
if asKey {
return je.EmitString("~_", false)
} else {
return je.EmitBase(nil)
}
}
func (je JsonEmitter) EmitFloat(f float64, asKey bool) error {
if asKey {
return je.EmitString(fmt.Sprintf("~d%g", f), asKey)
} else {
s := fmt.Sprintf("%g", f)
if !strings.ContainsAny(s, ".eE") {
s = s + ".0" // Horible hack!
}
return je.Emit(s)
}
}
func (je JsonEmitter) EmitStartArray() error {
return je.Emit("[")
}
func (je JsonEmitter) EmitEndArray() error {
return je.Emit("]")
}
func (je JsonEmitter) EmitArraySeparator() error {
return je.Emit(",")
}
func (je JsonEmitter) EmitStartMap() error {
return je.Emit("{")
}
func (je JsonEmitter) EmitEndMap() error {
return je.Emit("}")
}
func (je JsonEmitter) EmitMapSeparator() error {
return je.Emit(",")
}
func (je JsonEmitter) EmitKeySeparator() error {
return je.Emit(":")
}
func (je JsonEmitter) EmitBool(x bool, asKey bool) error {
if asKey {
if x {
return je.EmitString("~?t", false)
} else {
return je.EmitString("~?f", false)
}
} else {
return je.EmitBase(x)
}
}

212
vendor/github.com/russolsen/transit/encode.go generated vendored Normal file
View File

@@ -0,0 +1,212 @@
// Copyright 2016 Russ Olsen. All Rights Reserved.
//
// This code is a Go port of the Java version created and maintained by Cognitect, therefore:
//
// Copyright 2014 Cognitect. All Rights Reserved.
//
// 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 transit
import (
"bytes"
"container/list"
"github.com/pborman/uuid"
"github.com/shopspring/decimal"
"io"
"math/big"
"net/url"
"reflect"
"time"
)
type Encoder struct {
emitter DataEmitter
valueEncoders map[interface{}]ValueEncoder
}
var goListType = reflect.TypeOf(list.New())
var keywordType = reflect.TypeOf(Keyword(""))
var symbolType = reflect.TypeOf(Symbol(""))
var cmapType = reflect.TypeOf(NewCMap())
var aUrl, _ = url.Parse("http://foo.com")
var urlType = reflect.TypeOf(aUrl)
var turiType = reflect.TypeOf(NewTUri("http://example.com"))
var setType = reflect.TypeOf(Set{})
var timeType = reflect.TypeOf(time.Now())
var bigRatType = reflect.TypeOf(*big.NewRat(int64(1), int64(2)))
var bigIntType = reflect.TypeOf(*big.NewInt(int64(1)))
var bigFloatType = reflect.TypeOf(*big.NewFloat(float64(1.)))
var decimalType = reflect.TypeOf(decimal.NewFromFloat(3))
var uuidType = reflect.TypeOf(uuid.NewRandom())
var linkType = reflect.TypeOf(*NewLink())
var taggedValueType = reflect.TypeOf(TaggedValue{TagId("#foo"), 1})
var runeType = reflect.TypeOf('x')
var nilValue = reflect.ValueOf(nil)
var nilEncoder = NewNilEncoder()
// NewEncoder creates a new encoder set to writ to the stream supplied.
// The verbose parameter controls transit's verbose vs non-verbose mode.
// Generally for production you want verbose = false.
func NewEncoder(w io.Writer, verbose bool) *Encoder {
valueEncoders := make(map[interface{}]ValueEncoder)
var cache Cache
if verbose {
cache = NewNoopCache()
} else {
cache = NewRollingCache()
}
emitter := NewJsonEmitter(w, cache)
e := Encoder{emitter: emitter, valueEncoders: valueEncoders}
e.addHandler(reflect.String, NewStringEncoder())
e.addHandler(reflect.Bool, NewBoolEncoder())
e.addHandler(reflect.Ptr, NewPointerEncoder())
floatEncoder := NewFloatEncoder()
e.addHandler(reflect.Float32, floatEncoder)
e.addHandler(reflect.Float64, floatEncoder)
decimalEncoder := NewDecimalEncoder()
e.addHandler(decimalType, decimalEncoder)
intEncoder := NewIntEncoder()
e.addHandler(reflect.Int, intEncoder)
e.addHandler(reflect.Int8, intEncoder)
e.addHandler(reflect.Int16, intEncoder)
e.addHandler(reflect.Int32, intEncoder)
e.addHandler(reflect.Int64, intEncoder)
uintEncoder := NewUintEncoder()
e.addHandler(reflect.Uint, uintEncoder)
e.addHandler(reflect.Uint8, uintEncoder)
e.addHandler(reflect.Uint16, uintEncoder)
e.addHandler(reflect.Uint32, uintEncoder)
e.addHandler(reflect.Uint64, uintEncoder)
arrayEncoder := NewArrayEncoder()
e.addHandler(reflect.Array, arrayEncoder)
e.addHandler(reflect.Slice, arrayEncoder)
e.addHandler(reflect.Map, NewMapEncoder(verbose))
e.addHandler(runeType, NewRuneEncoder())
e.addHandler(timeType, NewTimeEncoder())
e.addHandler(uuidType, NewUuidEncoder())
e.addHandler(bigIntType, NewBigIntEncoder())
e.addHandler(bigRatType, NewBigRatEncoder())
e.addHandler(bigFloatType, NewBigFloatEncoder())
e.addHandler(goListType, NewListEncoder())
e.addHandler(symbolType, NewSymbolEncoder())
e.addHandler(keywordType, NewKeywordEncoder())
e.addHandler(cmapType, NewCMapEncoder())
e.addHandler(setType, NewSetEncoder())
e.addHandler(urlType, NewUrlEncoder())
e.addHandler(turiType, NewTUriEncoder())
e.addHandler(linkType, NewLinkEncoder())
e.addHandler(taggedValueType, NewTaggedValueEncoder())
return &e
}
// AddHandler adds a new handler to the table used by this encoder
// for encoding values. The t value should be an instance
// of reflect.Type and the c value should be an encoder for that type.
func (e Encoder) AddHandler(t reflect.Type, c ValueEncoder) {
e.addHandler(t, c)
}
// addHandler adds a new handler to the table, but the untyped first
// parameter lets you enter either reflect.Type or reflect.Kind values.
// Used internally.
func (e Encoder) addHandler(t interface{}, c ValueEncoder) {
e.valueEncoders[t] = c
}
// ValueEncoderFor finds the encoder for the given value.
func (e Encoder) ValueEncoderFor(v reflect.Value) ValueEncoder {
// Nil is a special case since it doesn't really work
// very well with the reflect package.
if v == nilValue {
return nilEncoder
}
// Look for an encoder by the specific type.
typeEncoder := e.valueEncoders[v.Type()]
if typeEncoder != nil {
return typeEncoder
}
// If we can't find a type encoder, try finding one
// by type. This is will catch values of know kinds,
// say int64 or string which have a different specific
// type.
kindEncoder := e.valueEncoders[v.Kind()]
if kindEncoder != nil {
return kindEncoder
}
// No encoder, for this type, return the error encoder.
return NewErrorEncoder()
}
// Given a Value, encode it.
func (e Encoder) EncodeValue(v reflect.Value, asKey bool) error {
valueEncoder := e.ValueEncoderFor(v)
return valueEncoder.Encode(e, v, asKey)
}
// Given a raw interface, encode it.
func (e Encoder) EncodeInterface(x interface{}, asKey bool) error {
v := reflect.ValueOf(x)
return e.EncodeValue(v, asKey)
}
// Encode a value at the top level.
func (e Encoder) Encode(x interface{}) error {
v := reflect.ValueOf(x)
valueEncoder := e.ValueEncoderFor(v)
if valueEncoder.IsStringable(v) {
x = TaggedValue{TagId("'"), x}
}
return e.EncodeInterface(x, false)
}
// Encode the given value to a string.
func EncodeToString(x interface{}, verbose bool) (string, error) {
var buf bytes.Buffer
var encoder = NewEncoder(&buf, verbose)
err := encoder.Encode(x)
if err != nil {
return "", err
}
return buf.String(), nil
}

32
vendor/github.com/russolsen/transit/error.go generated vendored Normal file
View File

@@ -0,0 +1,32 @@
// Copyright 2016 Russ Olsen. All Rights Reserved.
//
// This code is a Go port of the Java version created and maintained by Cognitect, therefore:
//
// Copyright 2014 Cognitect. All Rights Reserved.
//
// 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 transit
type TransitError struct {
Message string // Describe the error.
Source interface{} // The value that cause the problem.
}
func NewTransitError(msg string, v interface{}) *TransitError {
return &TransitError{Message: msg, Source: v}
}
func (e *TransitError) Error() string {
return e.Message
}

31
vendor/github.com/russolsen/transit/link.go generated vendored Normal file
View File

@@ -0,0 +1,31 @@
// Copyright 2016 Russ Olsen. All Rights Reserved.
//
// This code is a Go port of the Java version created and maintained by Cognitect, therefore:
//
// Copyright 2014 Cognitect. All Rights Reserved.
//
// 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 transit
type Link struct {
Href *TUri
Rel string
Name string
Prompt string
Render string
}
func NewLink() *Link {
return &Link{}
}

34
vendor/github.com/russolsen/transit/noop_cache.go generated vendored Normal file
View File

@@ -0,0 +1,34 @@
// Copyright 2016 Russ Olsen. All Rights Reserved.
//
// This code is a Go port of the Java version created and maintained by Cognitect, therefore:
//
// Copyright 2014 Cognitect. All Rights Reserved.
//
// 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 transit
// NoopCache is a do-nothing implementation of a cache.
type NoopCache struct{}
func NewNoopCache() *NoopCache {
return &NoopCache{}
}
func (c *NoopCache) IsCacheable(s string, asKey bool) bool {
return false
}
func (c *NoopCache) Write(s string) string {
return s
}

128
vendor/github.com/russolsen/transit/rolling_cache.go generated vendored Normal file
View File

@@ -0,0 +1,128 @@
// Copyright 2016 Russ Olsen. All Rights Reserved.
//
// This code is a Go port of the Java version created and maintained by Cognitect, therefore:
//
// Copyright 2014 Cognitect. All Rights Reserved.
//
// 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 transit
import (
"fmt"
)
const cacheCodeDigits = 44
const baseCharIndex = 48
const firstOrd = 48
const cacheSize = (cacheCodeDigits * cacheCodeDigits)
const minSizeCacheable = 4
type StringMap map[string]string
type RollingCache struct {
keyToValue StringMap
valueToKey StringMap
}
func NewRollingCache() *RollingCache {
return &RollingCache{keyToValue: make(StringMap), valueToKey: make(StringMap)}
}
func (rc *RollingCache) String() string {
return fmt.Sprintf("Cache: %v", rc.keyToValue)
}
func (rc *RollingCache) HasKey(name string) bool {
_, present := rc.keyToValue[name]
return present
}
func (rc *RollingCache) Read(name string) string {
return rc.keyToValue[name]
}
// Enter the name into the cache if it passes the cacheable critieria.
// Returns either the name or the value that was previously cached for
// the name.
func (rc *RollingCache) Write(name string) string {
existing_key, present := rc.valueToKey[name]
if present {
return existing_key
}
if rc.isCacheFull() {
rc.Clear()
}
var key = rc.encodeKey(len(rc.keyToValue))
rc.keyToValue[key] = name
rc.valueToKey[name] = key
return name
}
// IsCacheable returns true if the string is long enough to be cached
// and either asKey is true or the string represents a symbol, keyword
// or tag.
func (rc *RollingCache) IsCacheable(s string, asKey bool) bool {
if len(s) < minSizeCacheable {
return false
} else if asKey {
return true
} else {
var firstTwo = s[0:2]
//return firstTwo == "~#" || firstTwo == "~$" || firstTwo == "~:"
return firstTwo == startTag || firstTwo == startKW || firstTwo == startSym
}
}
// IsCacheKey returns true if the string looks like a cache key.
func (rc *RollingCache) IsCacheKey(name string) bool {
if len(name) == 0 {
return false
} else if (name[0:1] == sub) && (name != mapAsArray) {
return true
} else {
return false
}
}
func (rc *RollingCache) encodeKey(index int) string {
var hi = index / cacheCodeDigits
var lo = index % cacheCodeDigits
if hi == 0 {
return sub + string(lo+baseCharIndex)
} else {
return sub + string(hi+baseCharIndex) + string(lo+baseCharIndex)
}
}
func (rc *RollingCache) codeToIndex(s string) int {
var sz = len(s)
if sz == 2 {
return int(s[1]) - baseCharIndex
} else {
return ((int(s[1]) - baseCharIndex) * cacheCodeDigits) + (int(s[2]) - baseCharIndex)
}
}
func (rc *RollingCache) isCacheFull() bool {
return len(rc.keyToValue) >= cacheSize
}
func (rc *RollingCache) Clear() {
rc.valueToKey = make(StringMap)
rc.keyToValue = make(StringMap)
}

55
vendor/github.com/russolsen/transit/set.go generated vendored Normal file
View File

@@ -0,0 +1,55 @@
// Copyright 2016 Russ Olsen. All Rights Reserved.
//
// This code is a Go port of the Java version created and maintained by Cognitect, therefore:
//
// Copyright 2014 Cognitect. All Rights Reserved.
//
// 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 transit
import (
"fmt"
)
// A set is a very simple minded representation of a set, one that
// does not enforce any redundancy constraints. Just a box
// for sets read from transit.
type Set struct {
Contents []interface{}
}
func MakeSet(contents ...interface{}) *Set {
return &Set{Contents: contents}
}
func NewSet(contents []interface{}) *Set {
return &Set{Contents: contents}
}
func (s Set) String() string {
return fmt.Sprintf("Set[%v]: %v", len(s.Contents), s.Contents)
}
func (s Set) Contains(value interface{}, mf MatchF) bool {
for _, element := range s.Contents {
if mf(element, value) {
return true
}
}
return false
}
func (s Set) ContainsEq(value interface{}) bool {
return s.Contains(value, Equals)
}

84
vendor/github.com/russolsen/transit/types.go generated vendored Normal file
View File

@@ -0,0 +1,84 @@
// Copyright 2016 Russ Olsen. All Rights Reserved.
//
// This code is a Go port of the Java version created and maintained by Cognitect, therefore:
//
// Copyright 2014 Cognitect. All Rights Reserved.
//
// 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 transit
import (
"fmt"
"net/url"
)
// Cache is the interface for (obviously) caches. Implemented
// by RollingCache and NoopCache.
type Cache interface {
IsCacheable(s string, asKey bool) bool
Write(string) string
}
// MatchF is an equality function protocol used by
// sets and cmaps.
type MatchF func(a, b interface{}) bool
// Matches keys with a simple == test. Satisfies the
// MatchF protocol.
func Equals(a, b interface{}) bool {
return a == b
}
// A tag id represents a #tag in the transit protocol.
type TagId string
func (t TagId) String() string {
return fmt.Sprintf("[Tag: %s]", string(t))
}
// TaggedValue is a simple struct to hold the data from
// a transit #tag.
type TaggedValue struct {
Tag TagId
Value interface{}
}
// A Keyword is a transit keyword, really just a string by another type.
type Keyword string
func (k Keyword) String() string {
return fmt.Sprintf(":%s", string(k))
}
// A Symbol is a transit symbol, really just a string by another type.
type Symbol string
// A TUri is just a container for a uri string. Go url.URL cannot handle all
// of the non-ascii chars of transit uris, hence the need for this type.
type TUri struct {
Value string
}
func NewTUri(x string) *TUri {
return &TUri{Value: x}
}
func (turi TUri) ToURL() (*url.URL, error) {
return url.Parse(turi.Value)
}
func (turi TUri) String() string {
return turi.Value
}

63
vendor/github.com/russolsen/transit/utils.go generated vendored Normal file
View File

@@ -0,0 +1,63 @@
// Copyright 2016 Russ Olsen. All Rights Reserved.
//
// This code is a Go port of the Java version created and maintained by Cognitect, therefore:
//
// Copyright 2014 Cognitect. All Rights Reserved.
//
// 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 transit
import (
"reflect"
)
// GetMapElement pulls a value out of a map (represented by
// the m value). This function differs from the reflect.Value
// MapIndex in that the type and kind of the returned value
// reflect the type and kind of the element, not what was
// declared in the map.
func GetMapElement(m reflect.Value, key reflect.Value) reflect.Value {
element := m.MapIndex(key)
return reflect.ValueOf(element.Interface())
}
// GetElement pulls a value out of a array (represented by
// the array value). This function differs from the reflect.Value
// Index in that the type and kind of the returned value
// reflect the type and kind of the element, not what was
// declared in the array.
func GetElement(array reflect.Value, i int) reflect.Value {
element := array.Index(i)
return reflect.ValueOf(element.Interface())
}
// KeyValues returns the Values for the keys in a map.
func KeyValues(m reflect.Value) []reflect.Value {
keys := m.MapKeys()
result := make([]reflect.Value, len(keys))
for i, v := range keys {
result[i] = reflect.ValueOf(v.Interface())
}
return result
}
func IsGenericArray(x interface{}) bool {
switch x.(type) {
case []interface{}:
return true
default:
return false
}
}

276
vendor/github.com/russolsen/transit/value_decoder.go generated vendored Normal file
View File

@@ -0,0 +1,276 @@
// Copyright 2016 Russ Olsen. All Rights Reserved.
//
// This code is a Go port of the Java version created and maintained by Cognitect, therefore:
//
// Copyright 2014 Cognitect. All Rights Reserved.
//
// 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 transit
import (
"container/list"
"encoding/base64"
"github.com/pborman/uuid"
"github.com/shopspring/decimal"
"math"
"math/big"
"strconv"
"time"
)
// DecodeKeyword decodes ~: style keywords.
func DecodeKeyword(d Decoder, x interface{}) (interface{}, error) {
s := x.(string)
var result = Keyword(s)
return result, nil
}
// DecodeKeyword decodes ~$ style symbols.
func DecodeSymbol(d Decoder, x interface{}) (interface{}, error) {
s := x.(string)
var result = Symbol(s)
return result, nil
}
// DecodeIdentity returns the value unchanged.
func DecodeIdentity(d Decoder, x interface{}) (interface{}, error) {
return x, nil
}
// DecodeCMap decodes maps with composite keys.
func DecodeCMap(d Decoder, x interface{}) (interface{}, error) {
tagged := x.(TaggedValue)
if !IsGenericArray(tagged.Value) {
return nil, NewTransitError("Cmap contents are not an array.", tagged)
}
array := tagged.Value.([]interface{})
if (len(array) % 2) != 0 {
return nil, NewTransitError("Cmap contents must contain an even number of elements.", tagged)
}
var result = NewCMap()
l := len(array)
for i := 0; i < l; i += 2 {
key := array[i]
value := array[i+1]
result.Append(key, value)
}
return result, nil
}
// DecodeSet decodes a transit set into a transit.Set instance.
func DecodeSet(d Decoder, x interface{}) (interface{}, error) {
tagged := x.(TaggedValue)
if !IsGenericArray(tagged.Value) {
return nil, NewTransitError("Set contents are not an array.", tagged)
}
values := (tagged.Value).([]interface{})
result := NewSet(values)
return result, nil
}
// DecodeList decodes a transit list into a Go list.
func DecodeList(d Decoder, x interface{}) (interface{}, error) {
tagged := x.(TaggedValue)
if !IsGenericArray(tagged.Value) {
return nil, NewTransitError("List contents are not an array.", tagged)
}
values := (tagged.Value).([]interface{})
result := list.New()
for _, item := range values {
result.PushBack(item)
}
return result, nil
}
// DecodeQuote decodes a transit quoted value by simply returning the value.
func DecodeQuote(d Decoder, x interface{}) (interface{}, error) {
tagged := x.(TaggedValue)
return tagged.Value, nil
}
// DecodeRFC3339 decodes a time value into a Go time instance.
// TBD not 100% this covers all possible values.
func DecodeRFC3339(d Decoder, x interface{}) (interface{}, error) {
s := x.(string)
var result, err = time.Parse(time.RFC3339Nano, s)
return result, err
}
// DecodeTime decodes a time value represended as millis since 1970.
func DecodeTime(d Decoder, x interface{}) (interface{}, error) {
s := x.(string)
var millis, _ = strconv.ParseInt(s, 10, 64)
seconds := millis / 1000
remainder_millis := millis - (seconds * 1000)
nanos := remainder_millis * 1000000
result := time.Unix(seconds, nanos).UTC()
return result, nil
}
// DecodeBoolean decodes a transit boolean into a Go bool.
func DecodeBoolean(d Decoder, x interface{}) (interface{}, error) {
s := x.(string)
if s == "t" {
return true, nil
} else if s == "f" {
return false, nil
} else {
return nil, &TransitError{Message: "Unknown boolean value."}
}
}
// DecodeBigInteger decodes a transit big integer into a Go big.Int.
func DecodeBigInteger(d Decoder, x interface{}) (interface{}, error) {
s := x.(string)
result := new(big.Int)
_, good := result.SetString(s, 10)
if !good {
return nil, &TransitError{Message: "Unable to part big integer: " + s}
}
return result, nil
}
// DecodeInteger decodes a transit integer into a plain Go int64
func DecodeInteger(d Decoder, x interface{}) (interface{}, error) {
s := x.(string)
result, err := strconv.ParseInt(s, 10, 64)
return result, err
}
func newRational(a, b *big.Int) *big.Rat {
var r = big.NewRat(1, 1)
r.SetFrac(a, b)
return r
}
func toBigInt(x interface{}) (*big.Int, error) {
switch v := x.(type) {
default:
return nil, NewTransitError("Not a numeric value", v)
case *big.Int:
return v, nil
case int64:
return big.NewInt(v), nil
}
}
// DecodeRatio decodes a transit ratio into a Go big.Rat.
func DecodeRatio(d Decoder, x interface{}) (interface{}, error) {
tagged := x.(TaggedValue)
if !IsGenericArray(tagged.Value) {
return nil, NewTransitError("Ratio contents are not an array.", tagged)
}
values := (tagged.Value).([]interface{})
if len(values) != 2 {
return nil, NewTransitError("Ratio contents does not contain 2 elements.", tagged)
}
a, err := toBigInt(values[0])
if err != nil {
return nil, err
}
b, err := toBigInt(values[1])
if err != nil {
return nil, err
}
result := newRational(a, b)
return *result, nil
}
// DecodeRune decodes a transit char.
func DecodeRune(d Decoder, x interface{}) (interface{}, error) {
s := x.(string)
return rune(s[0]), nil
}
// DecodeFloat decodes the value into a float.
func DecodeFloat(d Decoder, x interface{}) (interface{}, error) {
s := x.(string)
return strconv.ParseFloat(s, 64)
}
// DecodeDecimal decodes a transit big decimal into decimal.Decimal.
func DecodeDecimal(d Decoder, x interface{}) (interface{}, error) {
s := x.(string)
return decimal.NewFromString((s))
}
// DecodeRatio decodes a transit null/nil.
func DecodeNil(d Decoder, x interface{}) (interface{}, error) {
return nil, nil
}
// DecodeRatio decodes a transit base64 encoded byte array into a
// Go byte array.
func DecodeByte(d Decoder, x interface{}) (interface{}, error) {
s := x.(string)
return base64.StdEncoding.DecodeString(s)
}
// DecodeLink decodes a transit link into an instance of Link.
func DecodeLink(d Decoder, x interface{}) (interface{}, error) {
tv := x.(TaggedValue)
v := tv.Value.(map[interface{}]interface{})
l := NewLink()
l.Href = v["href"].(*TUri)
l.Name = v["name"].(string)
l.Rel = v["rel"].(string)
l.Prompt = v["prompt"].(string)
l.Render = v["render"].(string)
return l, nil
}
// DecodeURI decodes a transit URI into an instance of TUri.
func DecodeURI(d Decoder, x interface{}) (interface{}, error) {
s := x.(string)
return NewTUri(s), nil
}
// DecodeUUID decodes a transit UUID into an instance of net/UUID
func DecodeUUID(d Decoder, x interface{}) (interface{}, error) {
s := x.(string)
var u = uuid.Parse(s)
if u == nil {
return nil, &TransitError{Message: "Unable to parse uuid [" + s + "]"}
}
return u, nil
}
// DecodeSpecialNumber decodes NaN, INF and -INF into their Go equivalents.
func DecodeSpecialNumber(d Decoder, x interface{}) (interface{}, error) {
tag := x.(string)
if tag == "NaN" {
return math.NaN(), nil
} else if tag == "INF" {
return math.Inf(1), nil
} else if tag == "-INF" {
return math.Inf(-1), nil
} else {
return nil, &TransitError{Message: "Bad special number:"}
}
}

680
vendor/github.com/russolsen/transit/value_encoders.go generated vendored Normal file
View File

@@ -0,0 +1,680 @@
// Copyright 2016 Russ Olsen. All Rights Reserved.
//
// This code is a Go port of the Java version created and maintained by Cognitect, therefore:
//
// Copyright 2014 Cognitect. All Rights Reserved.
//
// 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 transit
import (
"container/list"
"fmt"
"github.com/pborman/uuid"
"github.com/shopspring/decimal"
"log"
"math"
"math/big"
"net/url"
"reflect"
"time"
)
// ValueEncoder is the interface for objects that know how to
// transit encode a single value.
type ValueEncoder interface {
IsStringable(reflect.Value) bool
Encode(e Encoder, value reflect.Value, asString bool) error
}
type NilEncoder struct{}
func NewNilEncoder() *NilEncoder {
return &NilEncoder{}
}
func (ie NilEncoder) IsStringable(v reflect.Value) bool {
return true
}
func (ie NilEncoder) Encode(e Encoder, v reflect.Value, asKey bool) error {
return e.emitter.EmitNil(asKey)
}
type RuneEncoder struct{}
func NewRuneEncoder() *RuneEncoder {
return &RuneEncoder{}
}
func (ie RuneEncoder) IsStringable(v reflect.Value) bool {
return true
}
func (ie RuneEncoder) Encode(e Encoder, v reflect.Value, asKey bool) error {
r := v.Interface().(rune)
return e.emitter.EmitString(fmt.Sprintf("~c%c", r), asKey)
}
type PointerEncoder struct{}
func NewPointerEncoder() *PointerEncoder {
return &PointerEncoder{}
}
func (ie PointerEncoder) IsStringable(v reflect.Value) bool {
return false
}
func (ie PointerEncoder) Encode(e Encoder, v reflect.Value, asKey bool) error {
//log.Println("*** Defer pointer to:", v.Elem())
return e.EncodeInterface(v.Elem().Interface(), asKey)
}
type UuidEncoder struct{}
func NewUuidEncoder() *UuidEncoder {
return &UuidEncoder{}
}
func (ie UuidEncoder) IsStringable(v reflect.Value) bool {
return true
}
func (ie UuidEncoder) Encode(e Encoder, v reflect.Value, asKey bool) error {
u := v.Interface().(uuid.UUID)
return e.emitter.EmitString(fmt.Sprintf("~u%v", u.String()), asKey)
}
type TimeEncoder struct{}
func NewTimeEncoder() *TimeEncoder {
return &TimeEncoder{}
}
func (ie TimeEncoder) IsStringable(v reflect.Value) bool {
return true
}
func (ie TimeEncoder) Encode(e Encoder, v reflect.Value, asKey bool) error {
t := v.Interface().(time.Time)
nanos := t.UnixNano()
millis := nanos / int64(1000000)
//millis := t.Unix() * 1000
return e.emitter.EmitString(fmt.Sprintf("~m%d", millis), asKey)
}
type BoolEncoder struct{}
func NewBoolEncoder() *BoolEncoder {
return &BoolEncoder{}
}
func (ie BoolEncoder) IsStringable(v reflect.Value) bool {
return true
}
func (ie BoolEncoder) Encode(e Encoder, v reflect.Value, asKey bool) error {
b := v.Bool()
return e.emitter.EmitBool(b, asKey)
}
type FloatEncoder struct{}
func NewFloatEncoder() *FloatEncoder {
return &FloatEncoder{}
}
func (ie FloatEncoder) IsStringable(v reflect.Value) bool {
return true
}
func (ie FloatEncoder) Encode(e Encoder, v reflect.Value, asKey bool) error {
f := v.Float()
if math.IsNaN(f) {
return e.emitter.EmitString("~zNaN", asKey)
} else if math.IsInf(f, 1) {
return e.emitter.EmitString("~zINF", asKey)
} else if math.IsInf(f, -1) {
return e.emitter.EmitString("~z-INF", asKey)
} else {
return e.emitter.EmitFloat(f, asKey)
}
}
type DecimalEncoder struct{}
func NewDecimalEncoder() *DecimalEncoder {
return &DecimalEncoder{}
}
func (ie DecimalEncoder) IsStringable(v reflect.Value) bool {
return true
}
func (ie DecimalEncoder) Encode(e Encoder, v reflect.Value, asKey bool) error {
f := v.Interface().(decimal.Decimal)
return e.emitter.EmitString(fmt.Sprintf("~f%v", f.String()), asKey)
}
type BigFloatEncoder struct{}
func NewBigFloatEncoder() *BigFloatEncoder {
return &BigFloatEncoder{}
}
func (ie BigFloatEncoder) IsStringable(v reflect.Value) bool {
return true
}
func (ie BigFloatEncoder) Encode(e Encoder, v reflect.Value, asKey bool) error {
f := v.Interface().(big.Float)
return e.emitter.EmitString(fmt.Sprintf("~f%v", f.Text('f', 25)), asKey)
}
type BigIntEncoder struct{}
func NewBigIntEncoder() *BigIntEncoder {
return &BigIntEncoder{}
}
func (ie BigIntEncoder) IsStringable(v reflect.Value) bool {
return true
}
func (ie BigIntEncoder) Encode(e Encoder, v reflect.Value, asKey bool) error {
i := v.Interface().(big.Int)
return e.emitter.EmitString(fmt.Sprintf("~n%v", i.String()), asKey)
}
type BigRatEncoder struct{}
func NewBigRatEncoder() *BigRatEncoder {
return &BigRatEncoder{}
}
func (ie BigRatEncoder) IsStringable(v reflect.Value) bool {
return false
}
func (ie BigRatEncoder) Encode(e Encoder, v reflect.Value, asKey bool) error {
r := v.Interface().(big.Rat)
e.emitter.EmitStartArray()
e.emitter.EmitTag("ratio")
e.emitter.EmitArraySeparator()
e.emitter.EmitStartArray()
e.Encode(r.Num())
e.emitter.EmitArraySeparator()
e.Encode(r.Denom())
e.emitter.EmitEndArray()
return e.emitter.EmitEndArray()
}
type IntEncoder struct{}
func NewIntEncoder() *IntEncoder {
return &IntEncoder{}
}
func (ie IntEncoder) IsStringable(v reflect.Value) bool {
return true
}
func (ie IntEncoder) Encode(e Encoder, v reflect.Value, asKey bool) error {
return e.emitter.EmitInt(v.Int(), asKey)
}
type UintEncoder struct{}
func NewUintEncoder() *UintEncoder {
return &UintEncoder{}
}
func (ie UintEncoder) IsStringable(v reflect.Value) bool {
return true
}
func (ie UintEncoder) Encode(e Encoder, v reflect.Value, asKey bool) error {
return e.emitter.EmitInt(int64(v.Uint()), asKey)
}
type KeywordEncoder struct{}
func NewKeywordEncoder() *KeywordEncoder {
return &KeywordEncoder{}
}
func (ie KeywordEncoder) IsStringable(v reflect.Value) bool {
return true
}
func (ie KeywordEncoder) Encode(e Encoder, v reflect.Value, asKey bool) error {
s := v.String()
//log.Println("Encoding keyword:", s)
return e.emitter.EmitString("~:"+s, true)
}
type SymbolEncoder struct{}
func NewSymbolEncoder() *SymbolEncoder {
return &SymbolEncoder{}
}
func (ie SymbolEncoder) IsStringable(v reflect.Value) bool {
return true
}
func (ie SymbolEncoder) Encode(e Encoder, v reflect.Value, asKey bool) error {
s := v.String()
//log.Println("Encoding symbol:", s)
return e.emitter.EmitString("~$"+s, true)
}
type StringEncoder struct{}
func NewStringEncoder() *StringEncoder {
return &StringEncoder{}
}
func (ie StringEncoder) IsStringable(v reflect.Value) bool {
return true
}
func (ie StringEncoder) needsEscape(s string) bool {
if len(s) == 0 {
return false
}
firstCh := s[0:1]
return firstCh == start || firstCh == reserved || firstCh == sub
}
func (ie StringEncoder) Encode(e Encoder, v reflect.Value, asKey bool) error {
s := v.String()
if ie.needsEscape(s) {
s = "~" + s
}
return e.emitter.EmitString(s, asKey)
}
type UrlEncoder struct{}
func NewUrlEncoder() *UrlEncoder {
return &UrlEncoder{}
}
func (ie UrlEncoder) IsStringable(v reflect.Value) bool {
return true
}
func (ie UrlEncoder) Encode(e Encoder, v reflect.Value, asKey bool) error {
u := v.Interface().(*url.URL)
us := u.String()
return e.emitter.EmitString(fmt.Sprintf("~r%s", us), asKey)
}
type TUriEncoder struct{}
func NewTUriEncoder() *TUriEncoder {
return &TUriEncoder{}
}
func (ie TUriEncoder) IsStringable(v reflect.Value) bool {
return true
}
func (ie TUriEncoder) Encode(e Encoder, v reflect.Value, asKey bool) error {
u := v.Interface().(*TUri)
return e.emitter.EmitString(fmt.Sprintf("~r%s", u.Value), asKey)
}
type ErrorEncoder struct{}
func NewErrorEncoder() *ErrorEncoder {
return &ErrorEncoder{}
}
func (ie ErrorEncoder) IsStringable(v reflect.Value) bool {
return true
}
func (ie ErrorEncoder) Encode(e Encoder, v reflect.Value, asKey bool) error {
return NewTransitError("Dont know how to encode value", v)
}
type ArrayEncoder struct{}
func NewArrayEncoder() *ArrayEncoder {
return &ArrayEncoder{}
}
func (ie ArrayEncoder) IsStringable(v reflect.Value) bool {
return false
}
func (ie ArrayEncoder) Encode(e Encoder, v reflect.Value, asKey bool) error {
e.emitter.EmitStartArray()
l := v.Len()
for i := 0; i < l; i++ {
if i > 0 {
e.emitter.EmitArraySeparator()
}
element := v.Index(i)
err := e.EncodeInterface(element.Interface(), asKey)
if err != nil {
return err
}
}
return e.emitter.EmitEndArray()
}
type MapEncoder struct {
verbose bool
}
func NewMapEncoder(verbose bool) *MapEncoder {
return &MapEncoder{verbose}
}
func (me MapEncoder) IsStringable(v reflect.Value) bool {
return false
}
func (me MapEncoder) Encode(e Encoder, v reflect.Value, asKey bool) error {
keys := KeyValues(v)
if !me.allStringable(e, keys) {
return me.encodeCompositeMap(e, v)
} else if me.verbose {
return me.encodeVerboseMap(e, v)
} else {
return me.encodeNormalMap(e, v)
}
}
func (me MapEncoder) allStringable(e Encoder, keys []reflect.Value) bool {
for _, key := range keys {
valueEncoder := e.ValueEncoderFor(reflect.ValueOf(key.Interface()))
if !valueEncoder.IsStringable(key) {
return false
}
}
return true
}
func (me MapEncoder) encodeCompositeMap(e Encoder, v reflect.Value) error {
e.emitter.EmitStartArray()
e.emitter.EmitTag("cmap")
e.emitter.EmitArraySeparator()
e.emitter.EmitStartArray()
keys := KeyValues(v)
for i, key := range keys {
if i != 0 {
e.emitter.EmitArraySeparator()
}
err := e.EncodeValue(key, false)
if err != nil {
return err
}
e.emitter.EmitArraySeparator()
value := GetMapElement(v, key)
err = e.EncodeValue(value, false)
if err != nil {
return err
}
}
e.emitter.EmitEndArray()
return e.emitter.EmitEndArray()
}
func (me MapEncoder) encodeNormalMap(e Encoder, v reflect.Value) error {
//l := v.Len()
e.emitter.EmitStartArray()
e.emitter.EmitString("^ ", false)
keys := KeyValues(v)
for _, key := range keys {
e.emitter.EmitArraySeparator()
err := e.EncodeValue(key, true)
if err != nil {
return err
}
e.emitter.EmitArraySeparator()
value := GetMapElement(v, key)
err = e.EncodeValue(value, false)
if err != nil {
return err
}
}
return e.emitter.EmitEndArray()
}
func (me MapEncoder) encodeVerboseMap(e Encoder, v reflect.Value) error {
e.emitter.EmitStartMap()
keys := KeyValues(v)
for i, key := range keys {
if i != 0 {
e.emitter.EmitMapSeparator()
}
err := e.EncodeValue(key, true)
if err != nil {
return err
}
e.emitter.EmitKeySeparator()
value := GetMapElement(v, key)
err = e.EncodeValue(value, false)
if err != nil {
return err
}
}
return e.emitter.EmitEndMap()
}
type TaggedValueEncoder struct{}
func NewTaggedValueEncoder() *TaggedValueEncoder {
return &TaggedValueEncoder{}
}
func (ie TaggedValueEncoder) IsStringable(v reflect.Value) bool {
return false
}
func (ie TaggedValueEncoder) Encode(e Encoder, v reflect.Value, asKey bool) error {
t := v.Interface().(TaggedValue)
e.emitter.EmitStartArray()
e.emitter.EmitTag(string(t.Tag))
e.emitter.EmitArraySeparator()
e.EncodeInterface(t.Value, asKey)
return e.emitter.EmitEndArray()
}
type SetEncoder struct{}
func NewSetEncoder() *SetEncoder {
return &SetEncoder{}
}
func (ie SetEncoder) IsStringable(v reflect.Value) bool {
return false
}
func (ie SetEncoder) Encode(e Encoder, v reflect.Value, asKey bool) error {
s := v.Interface().(Set)
//log.Println("*** Encode set:", v)
//l := v.Len()
e.emitter.EmitStartArray()
e.emitter.EmitTag("set")
e.emitter.EmitArraySeparator()
e.emitter.EmitStartArray()
for i, element := range s.Contents {
if i != 0 {
e.emitter.EmitArraySeparator()
}
err := e.EncodeInterface(element, asKey)
if err != nil {
return err
}
}
e.emitter.EmitEndArray()
return e.emitter.EmitEndArray()
}
type ListEncoder struct{}
func NewListEncoder() *ListEncoder {
return &ListEncoder{}
}
func (ie ListEncoder) IsStringable(v reflect.Value) bool {
return false
}
func (ie ListEncoder) Encode(e Encoder, v reflect.Value, asKey bool) error {
lst := v.Interface().(*list.List)
e.emitter.EmitStartArray()
e.emitter.EmitTag("list")
e.emitter.EmitArraySeparator()
e.emitter.EmitStartArray()
first := true
for element := lst.Front(); element != nil; element = element.Next() {
if first {
first = false
} else {
e.emitter.EmitArraySeparator()
}
err := e.EncodeInterface(element.Value, asKey)
if err != nil {
log.Println("ERROR", err)
return err
}
}
e.emitter.EmitEndArray()
return e.emitter.EmitEndArray()
}
type CMapEncoder struct{}
func NewCMapEncoder() *CMapEncoder {
return &CMapEncoder{}
}
func (ie CMapEncoder) IsStringable(v reflect.Value) bool {
return false
}
func (ie CMapEncoder) Encode(e Encoder, v reflect.Value, asKey bool) error {
cmap := v.Interface().(*CMap)
//l := v.Len()
e.emitter.EmitStartArray()
e.emitter.EmitTag("cmap")
e.emitter.EmitArraySeparator()
e.emitter.EmitStartArray()
for i, entry := range cmap.Entries {
if i != 0 {
e.emitter.EmitArraySeparator()
}
err := e.EncodeInterface(entry.Key, false)
if err != nil {
return err
}
e.emitter.EmitArraySeparator()
err = e.EncodeInterface(entry.Value, false)
if err != nil {
return err
}
}
e.emitter.EmitEndArray()
return e.emitter.EmitEndArray()
}
type LinkEncoder struct{}
func NewLinkEncoder() *LinkEncoder {
return &LinkEncoder{}
}
func (ie LinkEncoder) IsStringable(v reflect.Value) bool {
return false
}
func (ie LinkEncoder) Encode(e Encoder, v reflect.Value, asKey bool) error {
link := v.Interface().(*Link)
e.emitter.EmitStartArray()
e.emitter.EmitTag("link")
e.emitter.EmitArraySeparator()
m := map[string]interface{}{
"href": link.Href,
"rel": link.Rel,
"name": link.Name,
"prompt": link.Prompt,
"render": link.Render,
}
e.Encode(m)
return e.emitter.EmitEndArray()
}