2
vendor/github.com/russolsen/transit/.gitignore
generated
vendored
Normal file
2
vendor/github.com/russolsen/transit/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
transit
|
||||
pkg
|
||||
202
vendor/github.com/russolsen/transit/LICENSE
generated
vendored
Normal file
202
vendor/github.com/russolsen/transit/LICENSE
generated
vendored
Normal 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
124
vendor/github.com/russolsen/transit/README.md
generated
vendored
Normal file
@@ -0,0 +1,124 @@
|
||||
# transit (go)
|
||||
|
||||
[](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
90
vendor/github.com/russolsen/transit/cmap.go
generated
vendored
Normal 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
33
vendor/github.com/russolsen/transit/const.go
generated
vendored
Normal 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
322
vendor/github.com/russolsen/transit/decode.go
generated
vendored
Normal 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
152
vendor/github.com/russolsen/transit/emitter.go
generated
vendored
Normal 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
212
vendor/github.com/russolsen/transit/encode.go
generated
vendored
Normal 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
32
vendor/github.com/russolsen/transit/error.go
generated
vendored
Normal 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
31
vendor/github.com/russolsen/transit/link.go
generated
vendored
Normal 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
34
vendor/github.com/russolsen/transit/noop_cache.go
generated
vendored
Normal 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
128
vendor/github.com/russolsen/transit/rolling_cache.go
generated
vendored
Normal 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
55
vendor/github.com/russolsen/transit/set.go
generated
vendored
Normal 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
84
vendor/github.com/russolsen/transit/types.go
generated
vendored
Normal 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
63
vendor/github.com/russolsen/transit/utils.go
generated
vendored
Normal 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
276
vendor/github.com/russolsen/transit/value_decoder.go
generated
vendored
Normal 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
680
vendor/github.com/russolsen/transit/value_encoders.go
generated
vendored
Normal 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()
|
||||
}
|
||||
Reference in New Issue
Block a user