├── .editorconfig ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── SPEC.md ├── cache.go ├── complex_test.go ├── cork.go ├── cork_test.go ├── decode.go ├── decode_test.go ├── doc.go ├── encode.go ├── encode_test.go ├── errors.go ├── fields.go ├── go.mod ├── go.sum ├── handle.go ├── handle_test.go ├── limits_test.go ├── reader.go ├── reader_any.go ├── reader_arr.go ├── reader_ext.go ├── reader_map.go ├── reader_ref.go ├── reader_val.go ├── reflect.go ├── registry.go ├── sort.go ├── util.go ├── writer.go ├── writer_any.go ├── writer_arr.go ├── writer_ext.go ├── writer_map.go └── writer_ref.go /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig coding styles definitions. For more information about the 2 | # properties used in this file, please see the EditorConfig documentation: 3 | # http://editorconfig.org/ 4 | 5 | root = true 6 | 7 | [*] 8 | charset = utf-8 9 | end_of_line = LF 10 | indent_size = 4 11 | indent_style = tab 12 | insert_final_newline = true 13 | trim_trailing_whitespace = true 14 | 15 | [*.{yml,json}] 16 | indent_size = 2 17 | indent_style = space 18 | 19 | [*.{md,diff}] 20 | trim_trailing_whitespace = false 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # ----------------------------------- 2 | # OS X 3 | # ----------------------------------- 4 | 5 | # Directory files 6 | .DS_Store 7 | .AppleDouble 8 | .LSOverride 9 | 10 | # Thumbnail files 11 | ._* 12 | 13 | # Files that might appear on external disk 14 | .Spotlight-V100 15 | .Trashes 16 | 17 | # Directories potentially created on remote AFP share 18 | .AppleDB 19 | .AppleDesktop 20 | Network Trash Folder 21 | Temporary Items 22 | .apdisk 23 | 24 | # ----------------------------------- 25 | # Files 26 | # ----------------------------------- 27 | 28 | *.test 29 | *.cover 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright © SurrealDB Ltd 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Copyright © SurrealDB Ltd 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | GO ?= CGO_ENABLED=0 go 16 | 17 | .PHONY: default 18 | default: 19 | @echo "Choose a Makefile target:" 20 | @$(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print " - " $$1}}' | sort 21 | 22 | .PHONY: clean 23 | clean: 24 | $(GO) clean -i 25 | 26 | .PHONY: tests 27 | tests: 28 | $(GO) test ./... 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cork 2 | 3 | An efficient binary serialisation format for Go (Golang). 4 | 5 | [![](https://img.shields.io/badge/status-1.0.0-ff00bb.svg?style=flat-square)](https://github.com/surrealdb/cork) [![](https://img.shields.io/badge/godoc-reference-blue.svg?style=flat-square)](https://godoc.org/github.com/surrealdb/cork) [![](https://goreportcard.com/badge/github.com/surrealdb/cork?style=flat-square)](https://goreportcard.com/report/github.com/surrealdb/cork) [![](https://img.shields.io/badge/license-Apache_License_2.0-00bfff.svg?style=flat-square)](https://github.com/surrealdb/cork) 6 | 7 | #### Features 8 | 9 | - Simple and efficient encoding 10 | - Based on MsgPack serialization algorithm 11 | - Stores go type information inside encoded data 12 | - Faster serialization than gob binary encoding 13 | - More efficient output data size than gob binary encoding 14 | - Serializes native go types, and arbritary structs or interfaces 15 | - Enables predetermined encoding for structs without run-time reflection 16 | - Allows serialization to and from maps, structs, slices, and nil interfaces 17 | 18 | #### Installation 19 | 20 | ```bash 21 | go get github.com/surrealdb/cork 22 | ``` 23 | -------------------------------------------------------------------------------- /SPEC.md: -------------------------------------------------------------------------------- 1 | # CORK 2 | 3 | CORK is a dynamic and static binary object serialization specification 4 | similar to GOB and MessagePack. CORK manages encoding and decoding binary 5 | data streams, for use in transmission of, or storage of data. 6 | 7 | ### Basics 8 | 9 | A CORK data stream is self-describing. Each data item in the stream is preceded 10 | by a description of its type, expressed in terms of a small set of predefined 11 | types. Pointers to values are not transmitted, but the contents are flattened 12 | and transmitted. 13 | 14 | To use gobs, create an Encoder and present it with a series of data items as 15 | values or addresses that can be dereferenced to values. The Encoder makes sure 16 | all type information is sent before it is needed. At the receive side, a Decoder 17 | retrieves values from the encoded stream and unpacks them into local variables. 18 | 19 | ### Types 20 | 21 | CORK has built in support for the following types: 22 | 23 | `nil`, `bool`, `string`, `[]byte`, `int8`, `int16`, `int32`, `int64`, `uint8`, 24 | `uint16`, `uint32`, `uint64`, `float32`, `float64`, `complex64`, `complex128`, 25 | `time.Time`, `[]`, `map[]` 26 | 27 | ### Structs 28 | 29 | When a struct is encountered whilst encoding (and that struct does not satisfy 30 | the Corker interface) then the struct will be encoded into the stream as a map 31 | with the keys encoded as strings, and the values as the relevant type. Any 32 | struct tags describing how the struct should be encoded will be used. 33 | 34 | ### Corkers 35 | 36 | CORK allows applications to define application-specific types to be added 37 | to the encoding format. Each extended type must be assigned a unique byte 38 | from 0x00 upto 0xFF. Application-specific types (otherwise known as Corkers) 39 | are able to encode themselves into a binary data value, and are able to 40 | decode themselves from that same binary data value. 41 | 42 | To define a custom type, an application must ensure that the type satisfies 43 | the Corker interface, and must then register the type using the Register 44 | method. 45 | 46 | If a custom type is found in the stream when decoding, but no type with the 47 | specified unique byte is registered, then the binary data value will be 48 | decoded as a raw binary data value. 49 | 50 | ### Encoding types 51 | 52 | | Encoding name | Byte range | Usage 53 | | :------------ | :---------------- | :---------------------------------------------- | 54 | | fixint | 0x00 ... 0x7F | A positive number from `0` to `127` 55 | | fixstr | 0x80 ... 0x9F | A string which is `0` to `(1<<5)-1` in length 56 | | fixbin | 0xA0 ... 0xAF | Binary data which is `0` to `(1<<4)-1` in length 57 | | fixext | 0xB0 ... 0xBF | A custom type which is `0` to `(1<<4)-1` in length 58 | | fixarr | 0xC0 ... 0xCF | A set whose length is between `0` to `(1<<4)-1` 59 | | fixmap | 0xD0 ... 0xDF | A map whose length is between `0` to `(1<<4)-1` 60 | | - | - | - 61 | | nil | 0xE0 | A `nil` value 62 | | true | 0xE1 | Boolean value which is `true` 63 | | false | 0xE2 | Boolean value which is `false` 64 | | time | 0xE3 | Timestamp with nanosecond precision 65 | | - | - | - 66 | | str8 | 0xE4 | A string up to `(1<<8)-1` in length 67 | | str16 | 0xE5 | A string up to `(1<<16)-1` in length 68 | | str32 | 0xE6 | A string up to `(1<<32)-1` in length 69 | | str64 | 0xE7 | A string up to `(1<<63)-1` in length 70 | | - | - | - 71 | | bin8 | 0xE8 | Binary data up to `(1<<8)-1` in length 72 | | bin16 | 0xE9 | Binary data up to `(1<<16)-1` in length 73 | | bin32 | 0xEA | Binary data up to `(1<<32)-1` in length 74 | | bin64 | 0xEB | Binary data up to `(1<<63)-1` in length 75 | | - | - | - 76 | | ext8 | 0xEC | A custom type up to `(1<<8)-1` in length 77 | | ext16 | 0xED | A custom type up to `(1<<16)-1` in length 78 | | ext32 | 0xEE | A custom type up to `(1<<32)-1` in length 79 | | ext64 | 0xEF | A custom type up to `(1<<63)-1` in length 80 | | - | - | 81 | | int8 | 0xF0 | A signed integer less than `(1<<7)-1` 82 | | int16 | 0xF1 | A signed integer less than `(1<<15)-1` 83 | | int32 | 0xF2 | A signed integer less than `(1<<31)-1` 84 | | int64 | 0xF3 | A signed integer less than `(1<<63)-1` 85 | | - | - | - 86 | | uint8 | 0xF4 | An unsigned integer less than `(1<<8)-1` 87 | | uint16 | 0xF5 | An unsigned integer less than `(1<<16)-1` 88 | | uint32 | 0xF6 | An unsigned integer less than `(1<<32)-1` 89 | | uint64 | 0xF7 | An unsigned integer less than `(1<<64)-1` 90 | | - | - | - 91 | | float32 | 0xF8 | A IEEE-754 32bit floating point number 92 | | float64 | 0xF9 | A IEEE-754 64bit floating point number 93 | | - | - | - 94 | | complex64 | 0xFA | A 64bit complex number 95 | | complex128 | 0xFB | A 128bit complex number 96 | | - | - | - 97 | | arr | 0xFC | A set whose length is greater than `(1<<4)-1` 98 | | map | 0xFD | A map whose length is greater than `(1<<4)-1` 99 | | sym | 0xFE | *Reserved for internal use* 100 | | alt | 0xFF | *Reserved for internal use* 101 | 102 | ### Encoding methods 103 | 104 | ##### nil 105 | 106 | A `nil` value is stored in `1` byte: 107 | 108 | +--------+ 109 | | 0xE0 | 110 | +--------+ 111 | 112 | ##### bool 113 | 114 | A `bool` value is stored in `1` byte: 115 | 116 | true: 117 | +--------+ 118 | | 0xE1 | 119 | +--------+ 120 | 121 | false: 122 | +--------+ 123 | | 0xE2 | 124 | +--------+ 125 | 126 | ##### time 127 | 128 | A `time` value is stored in `9` bytes: 129 | 130 | time: 131 | +--------+--------+--------+--------+--------+--------+--------+--------+--------+ 132 | | 0xE3 | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | 133 | +--------+--------+--------+--------+--------+--------+--------+--------+--------+ 134 | 135 | ##### numbers 136 | 137 | A `number` value is stored in `1`, `2`, `3`, `5`, or `9` bytes: 138 | 139 | fixint stores a positive integer from 0 to 127: 140 | +--------+ 141 | | 0x?? | 142 | +--------+ 143 | 144 | int8 stores a signed integer upto (1<<7)-1: 145 | +--------+--------+ 146 | | 0xF1 | ---- | 147 | +--------+--------+ 148 | 149 | int16 stores a signed integer upto (1<<15)-1: 150 | +--------+--------+--------+ 151 | | 0xF2 | ---- | ---- | 152 | +--------+--------+--------+ 153 | 154 | int32 stores a signed integer upto (1<<31)-1: 155 | +--------+--------+--------+--------+--------+ 156 | | 0xF3 | ---- | ---- | ---- | ---- | 157 | +--------+--------+--------+--------+--------+ 158 | 159 | int64 stores a signed integer upto (1<<63)-1: 160 | +--------+--------+--------+--------+--------+--------+--------+--------+--------+ 161 | | 0xF4 | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | 162 | +--------+--------+--------+--------+--------+--------+--------+--------+--------+ 163 | 164 | uint8 stores a signed integer upto (1<<8)-1: 165 | +--------+--------+ 166 | | 0xF6 | ---- | 167 | +--------+--------+ 168 | 169 | uint16 stores a signed integer upto (1<<16)-1: 170 | +--------+--------+--------+ 171 | | 0xF7 | ---- | ---- | 172 | +--------+--------+--------+ 173 | 174 | uint32 stores a signed integer upto (1<<32)-1: 175 | +--------+--------+--------+--------+--------+ 176 | | 0xF8 | ---- | ---- | ---- | ---- | 177 | +--------+--------+--------+--------+--------+ 178 | 179 | uint64 stores a signed integer upto (1<<64)-1: 180 | +--------+--------+--------+--------+--------+--------+--------+--------+--------+ 181 | | 0xF9 | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | 182 | +--------+--------+--------+--------+--------+--------+--------+--------+--------+ 183 | 184 | ##### floats 185 | 186 | A `float` value is stored in `5`, or `9` bytes: 187 | 188 | float32 stores a floating point number in IEEE 754 single precision format: 189 | +--------+--------+--------+--------+--------+ 190 | | 0xFA | ---- | ---- | ---- | ---- | 191 | +--------+--------+--------+--------+--------+ 192 | 193 | float64 stores a floating point number in IEEE 754 double precision format: 194 | +--------+--------+--------+--------+--------+--------+--------+--------+--------+ 195 | | 0xFB | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | 196 | +--------+--------+--------+--------+--------+--------+--------+--------+--------+ 197 | 198 | ##### strings 199 | 200 | A `string` value is stored in `1`, `2`, `3`, `5`, or `9` descriptive bytes in addition to the size of the string data: 201 | 202 | fixstr stores a string whose length is upto 31 bytes: 203 | +--------+========+ 204 | | 0x?? | data | 205 | +--------+========+ 206 | 207 | str8 stores a string whose length is upto (1<<8)-1 bytes: 208 | +--------+--------+========+ 209 | | 0xE4 | ---- | data | 210 | +--------+--------+========+ 211 | 212 | str16 stores a string whose length is upto (1<<16)-1 bytes: 213 | +--------+--------+--------+========+ 214 | | 0xE5 | ---- | ---- | data | 215 | +--------+--------+--------+========+ 216 | 217 | str32 stores a string whose length is upto (1<<32)-1 bytes: 218 | +--------+--------+--------+--------+--------+========+ 219 | | 0xE6 | ---- | ---- | ---- | ---- | data | 220 | +--------+--------+--------+--------+--------+========+ 221 | 222 | str64 stores a string whose length is upto (1<<64)-1 bytes: 223 | +--------+--------+--------+--------+--------+--------+--------+--------+--------+========+ 224 | | 0xE7 | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | data | 225 | +--------+--------+--------+--------+--------+--------+--------+--------+--------+========+ 226 | 227 | ##### binary 228 | 229 | A `binary` value is stored in `1`, `2`, `3`, `5`, or `9` descriptive bytes in addition to the size of the binary data: 230 | 231 | fixbin stores a byte array whose length is upto 15 bytes: 232 | +--------+========+ 233 | | 0xA? | data | 234 | +--------+========+ 235 | 236 | bin8 stores a byte array whose length is upto (1<<8)-1 bytes: 237 | +--------+--------+========+ 238 | | 0xE8 | ---- | data | 239 | +--------+--------+========+ 240 | 241 | bin16 stores a byte array whose length is upto (1<<16)-1 bytes: 242 | +--------+--------+--------+========+ 243 | | 0xE9 | ---- | ---- | data | 244 | +--------+--------+--------+========+ 245 | 246 | bin32 stores a byte array whose length is upto (1<<32)-1 bytes: 247 | +--------+--------+--------+--------+--------+========+ 248 | | 0xEA | ---- | ---- | ---- | ---- | data | 249 | +--------+--------+--------+--------+--------+========+ 250 | 251 | bin64 stores a byte array whose length is upto (1<<64)-1 bytes: 252 | +--------+--------+--------+--------+--------+--------+--------+--------+--------+========+ 253 | | 0xEB | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | data | 254 | +--------+--------+--------+--------+--------+--------+--------+--------+--------+========+ 255 | 256 | ##### custom 257 | 258 | A `custom` value is stored in `1`, `2`, `3`, `5`, or `9` descriptive bytes in addition to the size of the custom data: 259 | 260 | fixext stores a custom type whose length is upto 15 bytes: 261 | +--------+--------+========+ 262 | | 0xB? | type | data | 263 | +--------+--------+========+ 264 | 265 | ext8 stores a custom type whose length is upto (1<<8)-1 bytes: 266 | +--------+--------+--------+========+ 267 | | 0xEC | ---- | type | data | 268 | +--------+--------+--------+========+ 269 | 270 | ext16 stores a custom type whose length is upto (1<<16)-1 bytes: 271 | +--------+--------+--------+--------+========+ 272 | | 0xED | ---- | ---- | type | data | 273 | +--------+--------+--------+--------+========+ 274 | 275 | ext32 stores a custom type whose length is upto (1<<32)-1 bytes: 276 | +--------+--------+--------+--------+--------+--------+========+ 277 | | 0xEE | ---- | ---- | ---- | ---- | type | data | 278 | +--------+--------+--------+--------+--------+--------+========+ 279 | 280 | ext64 stores a custom type whose length is upto (1<<64)-1 bytes: 281 | +--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+========+ 282 | | 0xEF | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | type | data | 283 | +--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+========+ 284 | 285 | ##### set 286 | 287 | A `set` value is stored in `1`, or `2` descriptive bytes in addition to the set elements: 288 | 289 | fixarr stores a set whose length is upto 15 elements: 290 | +--------+ - - - - - - - -+ 291 | | 0xC? | Elements | 292 | +--------+ - - - - - - - -+ 293 | 294 | arr stores a set whose length is upto (1<<64)-1 elements: 295 | +--------+ - - - - - - - -+ - - - - - - - -+ 296 | | 0xFC | Length | Elements | 297 | +--------+ - - - - - - - -+ - - - - - - - -+ 298 | 299 | ##### map 300 | 301 | A `map` value is stored in `1`, or `2` descriptive bytes in addition to the map key-value pairs: 302 | 303 | fixmap stores a set whose length is upto 15 elements: 304 | +--------+ - - - - - - - -+ 305 | | 0xD? | Elements | 306 | +--------+ - - - - - - - -+ 307 | 308 | map stores a set whose length is upto (1<<64)-1 key-value pairs: 309 | +--------+ - - - - - - - -+ - - - - - - - -+ 310 | | 0xFD | Length | Elements | 311 | +--------+ - - - - - - - -+ - - - - - - - -+ 312 | -------------------------------------------------------------------------------- /cache.go: -------------------------------------------------------------------------------- 1 | // Copyright © SurrealDB Ltd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package cork 16 | 17 | import ( 18 | "reflect" 19 | "sync" 20 | ) 21 | 22 | const ( 23 | maybe int = iota 24 | yes 25 | no 26 | ) 27 | 28 | var c cache 29 | 30 | type cache struct { 31 | cl sync.RWMutex 32 | c map[reflect.Type]int 33 | sl sync.RWMutex 34 | s map[reflect.Type]int 35 | ml sync.RWMutex 36 | m map[reflect.Type][]*field 37 | } 38 | 39 | func init() { 40 | c = cache{ 41 | c: make(map[reflect.Type]int), 42 | s: make(map[reflect.Type]int), 43 | m: make(map[reflect.Type][]*field), 44 | } 45 | } 46 | 47 | func (c *cache) Has(t reflect.Type) bool { 48 | c.ml.RLock() 49 | val := c.m[t] != nil 50 | c.ml.RUnlock() 51 | return val 52 | } 53 | 54 | func (c *cache) Get(t reflect.Type) []*field { 55 | c.ml.RLock() 56 | val := c.m[t] 57 | c.ml.RUnlock() 58 | return val 59 | } 60 | 61 | func (c *cache) Set(t reflect.Type, fls []*field) { 62 | c.ml.Lock() 63 | c.m[t] = fls 64 | c.ml.Unlock() 65 | } 66 | 67 | func (c *cache) Corkable(t reflect.Type) bool { 68 | c.cl.RLock() 69 | switch c.c[t] { 70 | case yes: 71 | c.cl.RUnlock() 72 | return true 73 | case no: 74 | c.cl.RUnlock() 75 | return false 76 | default: 77 | c.cl.RUnlock() 78 | c.cl.Lock() 79 | defer c.cl.Unlock() 80 | if t.Implements(typeCorker) { 81 | c.c[t] = yes 82 | return true 83 | } else { 84 | c.c[t] = no 85 | return false 86 | } 87 | } 88 | } 89 | 90 | func (c *cache) Selfable(t reflect.Type) bool { 91 | c.sl.RLock() 92 | switch c.s[t] { 93 | case yes: 94 | c.sl.RUnlock() 95 | return true 96 | case no: 97 | c.sl.RUnlock() 98 | return false 99 | default: 100 | c.sl.RUnlock() 101 | c.sl.Lock() 102 | defer c.sl.Unlock() 103 | if t.Implements(typeSelfer) { 104 | c.s[t] = yes 105 | return true 106 | } else { 107 | c.s[t] = no 108 | return false 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /complex_test.go: -------------------------------------------------------------------------------- 1 | // Copyright © SurrealDB Ltd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package cork 16 | 17 | import ( 18 | "bytes" 19 | "math" 20 | "testing" 21 | "time" 22 | 23 | . "github.com/smartystreets/goconvey/convey" 24 | ) 25 | 26 | func TestComplex(t *testing.T) { 27 | 28 | tme, _ := time.Parse(time.RFC3339, "1987-06-22T08:00:00.123456789Z") 29 | 30 | Convey("*Custom will encode and decode", t, func() { 31 | 32 | var bit []byte 33 | 34 | var tmp Custom 35 | 36 | var val = &Custom{ 37 | Null: nil, 38 | Bool: true, 39 | String: "test", 40 | Bytes: []byte("test"), 41 | Time: tme, 42 | Int: int(1), 43 | Int8: int8(math.MaxInt8), 44 | Int16: int16(math.MaxInt16), 45 | Int32: int32(math.MaxInt32), 46 | Int64: int64(math.MaxInt64), 47 | Uint: uint(1), 48 | Uint8: uint8(math.MaxUint8), 49 | Uint16: uint16(math.MaxUint16), 50 | Uint32: uint32(math.MaxUint32), 51 | Uint64: uint64(math.MaxUint64), 52 | Float32: math.MaxFloat32, 53 | Float64: math.MaxFloat64, 54 | Complex64: complex64(math.Pi), 55 | Complex128: complex128(math.Pi), 56 | Any: "test", 57 | ArrBool: []bool{true, false}, 58 | ArrString: []string{"test", "test"}, 59 | ArrInt: []int{math.MinInt64, math.MinInt32, math.MinInt16, math.MinInt8, 0, math.MaxInt8, math.MaxInt16, math.MaxInt32, math.MaxInt64}, 60 | ArrInt8: []int8{math.MinInt8, 0, math.MaxInt8}, 61 | ArrInt16: []int16{math.MinInt16, math.MinInt8, 0, math.MaxInt8, math.MaxInt16}, 62 | ArrInt32: []int32{math.MinInt32, math.MinInt16, math.MinInt8, 0, math.MaxInt8, math.MaxInt16, math.MaxInt32}, 63 | ArrInt64: []int64{math.MinInt64, math.MinInt32, math.MinInt16, math.MinInt8, 0, math.MaxInt8, math.MaxInt16, math.MaxInt32, math.MaxInt64}, 64 | ArrUint: []uint{0, 1, math.MaxUint8, math.MaxUint16, math.MaxUint32, math.MaxUint64}, 65 | ArrUint8: []uint8{0, 1, math.MaxUint8}, 66 | ArrUint16: []uint16{0, 1, math.MaxUint8, math.MaxUint16}, 67 | ArrUint32: []uint32{0, 1, math.MaxUint8, math.MaxUint16, math.MaxUint32}, 68 | ArrUint64: []uint64{0, 1, math.MaxUint8, math.MaxUint16, math.MaxUint32, math.MaxUint64}, 69 | ArrFloat32: []float32{math.Pi, math.Pi}, 70 | ArrFloat64: []float64{math.Pi, math.Pi}, 71 | ArrComplex64: []complex64{math.Pi, math.Pi}, 72 | ArrComplex128: []complex128{math.Pi, math.Pi}, 73 | ArrTime: []time.Time{tme, tme, tme}, 74 | ArrAny: []interface{}{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18"}, 75 | ArrNo: "test", 76 | MapStringInt: map[string]int{"test": math.MaxInt64}, 77 | MapStringUint: map[string]uint{"test": math.MaxUint64}, 78 | MapStringBool: map[string]bool{"test": true}, 79 | MapStringString: map[string]string{"test": "test"}, 80 | MapIntAny: map[int]interface{}{math.MaxInt64: "test"}, 81 | MapUintAny: map[uint]interface{}{math.MaxUint64: "test"}, 82 | MapStringAny: map[string]interface{}{"test": "test"}, 83 | MapTimeAny: map[time.Time]interface{}{tme: "test"}, 84 | MapAnyAny: map[interface{}]interface{}{ 85 | "1": "1", "2": "2", "3": "3", "4": "4", "5": "5", "6": "6", "7": "7", "8": "8", "9": "9", 86 | "10": "10", "11": "11", "12": "12", "13": "13", "14": "14", "15": "15", "16": "16", "17": "17", "18": "18", 87 | }, 88 | MapNo: "test", 89 | CustomBool: CustomBool(true), 90 | CustomString: CustomString("test"), 91 | CustomInt: CustomInt(1), 92 | CustomInt8: CustomInt8(math.MaxInt8), 93 | CustomInt16: CustomInt16(math.MaxInt16), 94 | CustomInt32: CustomInt32(math.MaxInt32), 95 | CustomInt64: CustomInt64(math.MaxInt64), 96 | CustomUint: CustomUint(1), 97 | CustomUint8: CustomUint8(math.MaxUint8), 98 | CustomUint16: CustomUint16(math.MaxUint16), 99 | CustomUint32: CustomUint32(math.MaxUint32), 100 | CustomUint64: CustomUint64(math.MaxUint64), 101 | CustomFloat32: CustomFloat32(math.MaxFloat32), 102 | CustomFloat64: CustomFloat64(math.MaxFloat64), 103 | CustomAny: CustomAny("test"), 104 | Tignored: nil, 105 | Signored: nil, 106 | Cignored: nil, 107 | Testable: &Tested{Data: []byte("test"), Test: map[string]string{}, Temp: []string{}}, 108 | Selfable: &Selfed{Data: []byte("test"), Test: map[string]string{}, Temp: []string{}}, 109 | Corkable: &Corked{Data: []byte("test"), Test: map[string]string{}, Temp: []string{}}, 110 | Arrayble: []*Corked{{Data: []byte("test"), Test: map[string]string{}, Temp: []string{}}}, 111 | } 112 | 113 | val.Embedded.One = "test" 114 | val.Embedded.Two = 666 115 | val.Embedded.Ced = &Corked{Data: []byte("test"), Test: map[string]string{}, Temp: []string{}} 116 | val.Embedded.Sed = &Selfed{Data: []byte("test"), Test: map[string]string{}, Temp: []string{}} 117 | 118 | enc := NewEncoderBytes(&bit) 119 | eer := enc.Encode(val) 120 | So(eer, ShouldBeNil) 121 | 122 | dec := NewDecoderBytes(bit) 123 | der := dec.Decode(&tmp) 124 | So(der, ShouldBeNil) 125 | 126 | So(tmp, ShouldResemble, *val) 127 | 128 | }) 129 | 130 | Convey("*Complex will encode and decode", t, func() { 131 | 132 | var val = &Complex{ 133 | Bool: true, 134 | String: "test", 135 | Bytes: []byte("test"), 136 | Time: tme, 137 | Int: -1, 138 | Int8: math.MaxInt8, 139 | Int16: math.MaxInt16, 140 | Int32: math.MaxInt32, 141 | Int64: math.MaxInt64, 142 | Uint: 1, 143 | Uint8: math.MaxUint8, 144 | Uint16: math.MaxUint16, 145 | Uint32: math.MaxUint32, 146 | Uint64: math.MaxUint64, 147 | Float32: math.MaxFloat32, 148 | Float64: math.MaxFloat64, 149 | Complex64: complex64(math.Pi), 150 | Complex128: complex128(math.Pi), 151 | Any: "test", 152 | ArrBool: []bool{true, false}, 153 | ArrString: []string{"test", "test"}, 154 | ArrInt: []int{math.MinInt64, math.MinInt32, math.MinInt16, math.MinInt8, 0, math.MaxInt8, math.MaxInt16, math.MaxInt32, math.MaxInt64}, 155 | ArrInt8: []int8{math.MinInt8, 0, math.MaxInt8}, 156 | ArrInt16: []int16{math.MinInt16, math.MinInt8, 0, math.MaxInt8, math.MaxInt16}, 157 | ArrInt32: []int32{math.MinInt32, math.MinInt16, math.MinInt8, 0, math.MaxInt8, math.MaxInt16, math.MaxInt32}, 158 | ArrInt64: []int64{math.MinInt64, math.MinInt32, math.MinInt16, math.MinInt8, 0, math.MaxInt8, math.MaxInt16, math.MaxInt32, math.MaxInt64}, 159 | ArrUint: []uint{0, 1, math.MaxUint8, math.MaxUint16, math.MaxUint32, math.MaxUint64}, 160 | ArrUint8: []uint8{0, 1, math.MaxUint8}, 161 | ArrUint16: []uint16{0, 1, math.MaxUint8, math.MaxUint16}, 162 | ArrUint32: []uint32{0, 1, math.MaxUint8, math.MaxUint16, math.MaxUint32}, 163 | ArrUint64: []uint64{0, 1, math.MaxUint8, math.MaxUint16, math.MaxUint32, math.MaxUint64}, 164 | ArrFloat32: []float32{math.Pi, math.Pi}, 165 | ArrFloat64: []float64{math.Pi, math.Pi}, 166 | ArrComplex64: []complex64{math.Pi, math.Pi}, 167 | ArrComplex128: []complex128{math.Pi, math.Pi}, 168 | ArrTime: []time.Time{tme, tme, tme}, 169 | ArrAny: []interface{}{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18"}, 170 | ArrNo: "test", 171 | MapStringInt: map[string]int{"test": math.MaxInt64}, 172 | MapStringUint: map[string]uint{"test": math.MaxUint64}, 173 | MapStringBool: map[string]bool{"test": true}, 174 | MapStringString: map[string]string{"test": "test"}, 175 | MapIntAny: map[int]interface{}{math.MaxInt64: "test"}, 176 | MapUintAny: map[uint]interface{}{math.MaxUint64: "test"}, 177 | MapStringAny: map[string]interface{}{"test": "test"}, 178 | MapTimeAny: map[time.Time]interface{}{tme: "test"}, 179 | MapAnyAny: map[interface{}]interface{}{ 180 | "1": "1", "2": "2", "3": "3", "4": "4", "5": "5", "6": "6", "7": "7", "8": "8", "9": "9", 181 | "10": "10", "11": "11", "12": "12", "13": "13", "14": "14", "15": "15", "16": "16", "17": "17", "18": "18", 182 | }, 183 | MapNo: "test", 184 | } 185 | 186 | var dst Complex 187 | var tmp interface{} 188 | 189 | enb := bytes.NewBuffer(nil) 190 | enc := NewEncoder(enb) 191 | eer := enc.Encode(val) 192 | src := enb.Bytes() 193 | 194 | deb := bytes.NewReader(src) 195 | dec := NewDecoder(deb) 196 | der := dec.Decode(&dst) 197 | 198 | teb := bytes.NewReader(src) 199 | tec := NewDecoder(teb) 200 | ter := tec.Decode(&tmp) 201 | 202 | So(eer, ShouldBeNil) 203 | So(der, ShouldBeNil) 204 | So(ter, ShouldBeNil) 205 | 206 | So(src, ShouldNotBeNil) 207 | So(dst, ShouldNotBeNil) 208 | So(tmp, ShouldNotBeNil) 209 | 210 | So(dst, ShouldResemble, *val) 211 | So(tmp, ShouldResemble, val) 212 | 213 | }) 214 | 215 | } 216 | -------------------------------------------------------------------------------- /cork.go: -------------------------------------------------------------------------------- 1 | // Copyright © SurrealDB Ltd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package cork 16 | 17 | const tag = "cork" 18 | 19 | const ( 20 | fixedInt = 1<<7 - 1 // 127 21 | fixedStr = 1<<5 - 1 // 31 22 | fixedBin = 1<<4 - 1 // 15 23 | fixedExt = 1<<4 - 1 // 15 24 | fixedArr = 1<<4 - 1 // 16 25 | fixedMap = 1<<4 - 1 // 16 26 | ) 27 | 28 | const ( 29 | cFixInt byte = 0x00 // -> 0x7F = 128 30 | cFixStr = 0x80 // -> 0x9F = 32 31 | cFixBin = 0xA0 // -> 0xAf = 16 32 | cFixExt = 0xB0 // -> 0xBF = 16 33 | cFixArr = 0xC0 // -> 0xCF = 16 34 | cFixMap = 0xD0 // -> 0xDF = 16 35 | _ = 0 36 | cNil = 0xE0 37 | cTrue = 0xE1 38 | cFalse = 0xE2 39 | cTime = 0xE3 40 | _ = 0 41 | cStr8 = 0xE4 42 | cStr16 = 0xE5 43 | cStr32 = 0xE6 44 | cStr64 = 0xE7 45 | _ = 0 46 | cBin8 = 0xE8 47 | cBin16 = 0xE9 48 | cBin32 = 0xEA 49 | cBin64 = 0xEB 50 | _ = 0 51 | cExt8 = 0xEC 52 | cExt16 = 0xED 53 | cExt32 = 0xEE 54 | cExt64 = 0xEF 55 | _ = 0 56 | cInt8 = 0xF0 57 | cInt16 = 0xF1 58 | cInt32 = 0xF2 59 | cInt64 = 0xF3 60 | _ = 0 61 | cUint8 = 0xF4 62 | cUint16 = 0xF5 63 | cUint32 = 0xF6 64 | cUint64 = 0xF7 65 | _ = 0 66 | cFloat32 = 0xF8 67 | cFloat64 = 0xF9 68 | _ = 0 69 | cComplex64 = 0xFA 70 | cComplex128 = 0xFB 71 | _ = 0 72 | cArr = 0xFC 73 | cMap = 0xFD 74 | cSlf = 0xFE 75 | cAlt = 0xFF 76 | _ = 0 77 | ) 78 | 79 | // Corker represents an object which can encode and decode itself. 80 | type Corker interface { 81 | ExtendCORK() byte 82 | MarshalCORK() ([]byte, error) 83 | UnmarshalCORK([]byte) error 84 | } 85 | 86 | // Selfer represents an object which can encode and decode itself. 87 | type Selfer interface { 88 | ExtendCORK() byte 89 | MarshalCORK(*Writer) error 90 | UnmarshalCORK(*Reader) error 91 | } 92 | -------------------------------------------------------------------------------- /cork_test.go: -------------------------------------------------------------------------------- 1 | // Copyright © SurrealDB Ltd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package cork 16 | 17 | import ( 18 | "bytes" 19 | "errors" 20 | "fmt" 21 | "math" 22 | "reflect" 23 | "testing" 24 | "time" 25 | 26 | . "github.com/smartystreets/goconvey/convey" 27 | ) 28 | 29 | // ---------------------------------------------------------------------- 30 | 31 | var handle = &Handle{ 32 | ArrType: make([]interface{}, 0), 33 | MapType: make(map[string]interface{}), 34 | } 35 | 36 | // ---------------------------------------------------------------------- 37 | 38 | type CustomAny interface{} 39 | type CustomBool bool 40 | type CustomInt int 41 | type CustomInt8 int8 42 | type CustomInt16 int16 43 | type CustomInt32 int32 44 | type CustomInt64 int64 45 | type CustomUint uint 46 | type CustomUint8 uint8 47 | type CustomUint16 uint16 48 | type CustomUint32 uint32 49 | type CustomUint64 uint64 50 | type CustomFloat32 float32 51 | type CustomFloat64 float64 52 | type CustomString string 53 | 54 | type Custom struct { 55 | Nil interface{} 56 | Null interface{} 57 | Bool bool 58 | String string 59 | Bytes []byte 60 | Time time.Time 61 | Int int 62 | Int8 int8 63 | Int16 int16 64 | Int32 int32 65 | Int64 int64 66 | Uint uint 67 | Uint8 uint8 68 | Uint16 uint16 69 | Uint32 uint32 70 | Uint64 uint64 71 | Float32 float32 72 | Float64 float64 73 | Complex64 complex64 74 | Complex128 complex128 75 | Any interface{} 76 | ArrBool []bool 77 | ArrString []string 78 | ArrInt []int 79 | ArrInt8 []int8 80 | ArrInt16 []int16 81 | ArrInt32 []int32 82 | ArrInt64 []int64 83 | ArrUint []uint 84 | ArrUint8 []uint8 85 | ArrUint16 []uint16 86 | ArrUint32 []uint32 87 | ArrUint64 []uint64 88 | ArrFloat32 []float32 89 | ArrFloat64 []float64 90 | ArrComplex64 []complex64 91 | ArrComplex128 []complex128 92 | ArrTime []time.Time 93 | ArrAny []interface{} 94 | ArrNo string 95 | MapStringInt map[string]int 96 | MapStringUint map[string]uint 97 | MapStringBool map[string]bool 98 | MapStringString map[string]string 99 | MapIntAny map[int]interface{} 100 | MapUintAny map[uint]interface{} 101 | MapStringAny map[string]interface{} 102 | MapTimeAny map[time.Time]interface{} 103 | MapAnyAny map[interface{}]interface{} 104 | MapNo string 105 | CustomBool CustomBool 106 | CustomString CustomString 107 | CustomInt CustomInt 108 | CustomInt8 CustomInt8 109 | CustomInt16 CustomInt16 110 | CustomInt32 CustomInt32 111 | CustomInt64 CustomInt64 112 | CustomUint CustomUint 113 | CustomUint8 CustomUint8 114 | CustomUint16 CustomUint16 115 | CustomUint32 CustomUint32 116 | CustomUint64 CustomUint64 117 | CustomFloat32 CustomFloat32 118 | CustomFloat64 CustomFloat64 119 | CustomAny CustomAny 120 | Tignored *Tested 121 | Signored *Selfed 122 | Cignored *Corked 123 | Testable *Tested 124 | Selfable *Selfed 125 | Corkable *Corked 126 | Funcable func() 127 | Chanable chan int 128 | Arrayble []*Corked 129 | Embedded struct { 130 | One string 131 | Two int 132 | Ced *Corked 133 | Sed *Selfed 134 | } 135 | } 136 | 137 | // ---------------------------------------------------------------------- 138 | 139 | type CustomTextFailer struct { 140 | Field string 141 | } 142 | 143 | func (this *CustomTextFailer) MarshalText() ([]byte, error) { 144 | return nil, errors.New("Marshal error") 145 | } 146 | 147 | func (this *CustomTextFailer) UnmarshalText(v []byte) error { 148 | return errors.New("Unmarshal error") 149 | } 150 | 151 | type CustomBinaryFailer struct { 152 | Field string 153 | } 154 | 155 | func (this *CustomBinaryFailer) MarshalBinary() ([]byte, error) { 156 | return nil, errors.New("Marshal error") 157 | } 158 | 159 | func (this *CustomBinaryFailer) UnmarshalBinary(v []byte) error { 160 | return errors.New("Unmarshal error") 161 | } 162 | 163 | // ---------------------------------------------------------------------- 164 | 165 | type CustomTextMarshaler struct { 166 | Field string 167 | } 168 | 169 | func (this *CustomTextMarshaler) MarshalText() ([]byte, error) { 170 | return []byte(this.Field), nil 171 | } 172 | 173 | func (this *CustomTextMarshaler) UnmarshalText(v []byte) error { 174 | this.Field = string(v) 175 | return nil 176 | } 177 | 178 | type CustomBinaryMarshaler struct { 179 | Field string 180 | } 181 | 182 | func (this *CustomBinaryMarshaler) MarshalBinary() ([]byte, error) { 183 | return []byte(this.Field), nil 184 | } 185 | 186 | func (this *CustomBinaryMarshaler) UnmarshalBinary(v []byte) error { 187 | this.Field = string(v) 188 | return nil 189 | } 190 | 191 | // ---------------------------------------------------------------------- 192 | 193 | type Tested struct { 194 | Name string 195 | Data []byte `cork:"data"` 196 | Temp []string 197 | Test map[string]string 198 | priv bool 199 | Count int 200 | Omit string `cork:"-"` 201 | Empty string `cork:",omitempty"` 202 | } 203 | 204 | // ---------------------------------------------------------------------- 205 | 206 | type Errord struct{} 207 | 208 | func (this *Errord) ExtendCORK() byte { 209 | return 0x00 210 | } 211 | 212 | func (this *Errord) MarshalCORK() (dst []byte, err error) { 213 | return nil, errors.New("Marshal error") 214 | } 215 | 216 | func (this *Errord) UnmarshalCORK(src []byte) (err error) { 217 | return errors.New("Unmarshal error") 218 | } 219 | 220 | // ---------------------------------------------------------------------- 221 | 222 | type Simple struct{} 223 | 224 | func (this *Simple) ExtendCORK() byte { 225 | return 0x01 226 | } 227 | 228 | func (this *Simple) MarshalCORK() (dst []byte, err error) { 229 | return 230 | } 231 | 232 | func (this *Simple) UnmarshalCORK(src []byte) (err error) { 233 | return 234 | } 235 | 236 | // ---------------------------------------------------------------------- 237 | 238 | type Corked struct { 239 | Name string 240 | Data []byte `cork:"data"` 241 | Temp []string `cork:"-"` 242 | Test map[string]string 243 | priv bool 244 | Count int 245 | Omit string `cork:"-"` 246 | Empty string `cork:",omitempty"` 247 | } 248 | 249 | func (this *Corked) ExtendCORK() byte { 250 | return 0x02 251 | } 252 | 253 | func (this *Corked) MarshalCORK() (dst []byte, err error) { 254 | b := bytes.NewBuffer(dst) 255 | e := NewEncoder(b) 256 | e.Encode(this.Name) 257 | e.Encode(this.Data) 258 | e.Encode(this.Temp) 259 | e.Encode(this.Test) 260 | e.Encode(this.Count) 261 | return b.Bytes(), nil 262 | } 263 | 264 | func (this *Corked) UnmarshalCORK(src []byte) (err error) { 265 | b := bytes.NewBuffer(src) 266 | d := NewDecoder(b) 267 | d.Decode(&this.Name) 268 | d.Decode(&this.Data) 269 | d.Decode(&this.Temp) 270 | d.Decode(&this.Test) 271 | d.Decode(&this.Count) 272 | return 273 | } 274 | 275 | // ---------------------------------------------------------------------- 276 | 277 | type Selfed struct { 278 | Name string 279 | Data []byte `cork:"data"` 280 | Temp []string `cork:"-"` 281 | Test map[string]string 282 | priv bool 283 | Count int 284 | Omit string `cork:"-"` 285 | Empty string `cork:",omitempty"` 286 | } 287 | 288 | func (this *Selfed) ExtendCORK() byte { 289 | return 0x03 290 | } 291 | 292 | func (this *Selfed) MarshalCORK(w *Writer) (err error) { 293 | w.EncodeString(this.Name) 294 | w.EncodeBytes(this.Data) 295 | w.EncodeArr(this.Temp) 296 | w.EncodeMap(this.Test) 297 | w.EncodeInt(this.Count) 298 | return 299 | } 300 | 301 | func (this *Selfed) UnmarshalCORK(r *Reader) (err error) { 302 | r.DecodeString(&this.Name) 303 | r.DecodeBytes(&this.Data) 304 | r.DecodeArr(&this.Temp) 305 | r.DecodeMap(&this.Test) 306 | r.DecodeInt(&this.Count) 307 | return 308 | } 309 | 310 | // ---------------------------------------------------------------------- 311 | 312 | type Complex struct { 313 | Bool bool 314 | String string 315 | Bytes []byte 316 | Time time.Time 317 | Int int 318 | Int8 int8 319 | Int16 int16 320 | Int32 int32 321 | Int64 int64 322 | Uint uint 323 | Uint8 uint8 324 | Uint16 uint16 325 | Uint32 uint32 326 | Uint64 uint64 327 | Float32 float32 328 | Float64 float64 329 | Complex64 complex64 330 | Complex128 complex128 331 | Any interface{} 332 | ArrBool []bool 333 | ArrString []string 334 | ArrInt []int 335 | ArrInt8 []int8 336 | ArrInt16 []int16 337 | ArrInt32 []int32 338 | ArrInt64 []int64 339 | ArrUint []uint 340 | ArrUint8 []uint8 341 | ArrUint16 []uint16 342 | ArrUint32 []uint32 343 | ArrUint64 []uint64 344 | ArrFloat32 []float32 345 | ArrFloat64 []float64 346 | ArrComplex64 []complex64 347 | ArrComplex128 []complex128 348 | ArrTime []time.Time 349 | ArrAny []interface{} 350 | ArrNo string 351 | MapStringInt map[string]int 352 | MapStringUint map[string]uint 353 | MapStringBool map[string]bool 354 | MapStringString map[string]string 355 | MapIntAny map[int]interface{} 356 | MapUintAny map[uint]interface{} 357 | MapStringAny map[string]interface{} 358 | MapTimeAny map[time.Time]interface{} 359 | MapAnyAny map[interface{}]interface{} 360 | MapNo string 361 | } 362 | 363 | func (this *Complex) ExtendCORK() byte { 364 | return 0x04 365 | } 366 | 367 | func (this *Complex) MarshalCORK(w *Writer) (err error) { 368 | w.EncodeBool(this.Bool) 369 | w.EncodeString(this.String) 370 | w.EncodeBytes(this.Bytes) 371 | w.EncodeTime(this.Time) 372 | w.EncodeInt(this.Int) 373 | w.EncodeInt8(this.Int8) 374 | w.EncodeInt16(this.Int16) 375 | w.EncodeInt32(this.Int32) 376 | w.EncodeInt64(this.Int64) 377 | w.EncodeUint(this.Uint) 378 | w.EncodeUint8(this.Uint8) 379 | w.EncodeUint16(this.Uint16) 380 | w.EncodeUint32(this.Uint32) 381 | w.EncodeUint64(this.Uint64) 382 | w.EncodeFloat32(this.Float32) 383 | w.EncodeFloat64(this.Float64) 384 | w.EncodeComplex64(this.Complex64) 385 | w.EncodeComplex128(this.Complex128) 386 | w.EncodeAny(this.Any) 387 | w.EncodeArr(this.ArrBool) 388 | w.EncodeArr(this.ArrString) 389 | w.EncodeArr(this.ArrInt) 390 | w.EncodeArr(this.ArrInt8) 391 | w.EncodeArr(this.ArrInt16) 392 | w.EncodeArr(this.ArrInt32) 393 | w.EncodeArr(this.ArrInt64) 394 | w.EncodeArr(this.ArrUint) 395 | w.EncodeArr(this.ArrUint8) 396 | w.EncodeArr(this.ArrUint16) 397 | w.EncodeArr(this.ArrUint32) 398 | w.EncodeArr(this.ArrUint64) 399 | w.EncodeArr(this.ArrFloat32) 400 | w.EncodeArr(this.ArrFloat64) 401 | w.EncodeArr(this.ArrComplex64) 402 | w.EncodeArr(this.ArrComplex128) 403 | w.EncodeArr(this.ArrTime) 404 | w.EncodeArr(this.ArrAny) 405 | w.EncodeArr(this.ArrNo) 406 | w.EncodeMap(this.MapStringInt) 407 | w.EncodeMap(this.MapStringUint) 408 | w.EncodeMap(this.MapStringBool) 409 | w.EncodeMap(this.MapStringString) 410 | w.EncodeMap(this.MapIntAny) 411 | w.EncodeMap(this.MapUintAny) 412 | w.EncodeMap(this.MapStringAny) 413 | w.EncodeMap(this.MapTimeAny) 414 | w.EncodeMap(this.MapAnyAny) 415 | w.EncodeMap(this.MapNo) 416 | return 417 | } 418 | 419 | func (this *Complex) UnmarshalCORK(r *Reader) (err error) { 420 | r.DecodeBool(&this.Bool) 421 | r.DecodeString(&this.String) 422 | r.DecodeBytes(&this.Bytes) 423 | r.DecodeTime(&this.Time) 424 | r.DecodeInt(&this.Int) 425 | r.DecodeInt8(&this.Int8) 426 | r.DecodeInt16(&this.Int16) 427 | r.DecodeInt32(&this.Int32) 428 | r.DecodeInt64(&this.Int64) 429 | r.DecodeUint(&this.Uint) 430 | r.DecodeUint8(&this.Uint8) 431 | r.DecodeUint16(&this.Uint16) 432 | r.DecodeUint32(&this.Uint32) 433 | r.DecodeUint64(&this.Uint64) 434 | r.DecodeFloat32(&this.Float32) 435 | r.DecodeFloat64(&this.Float64) 436 | r.DecodeComplex64(&this.Complex64) 437 | r.DecodeComplex128(&this.Complex128) 438 | r.DecodeAny(&this.Any) 439 | r.DecodeArr(&this.ArrBool) 440 | r.DecodeArr(&this.ArrString) 441 | r.DecodeArr(&this.ArrInt) 442 | r.DecodeArr(&this.ArrInt8) 443 | r.DecodeArr(&this.ArrInt16) 444 | r.DecodeArr(&this.ArrInt32) 445 | r.DecodeArr(&this.ArrInt64) 446 | r.DecodeArr(&this.ArrUint) 447 | r.DecodeArr(&this.ArrUint8) 448 | r.DecodeArr(&this.ArrUint16) 449 | r.DecodeArr(&this.ArrUint32) 450 | r.DecodeArr(&this.ArrUint64) 451 | r.DecodeArr(&this.ArrFloat32) 452 | r.DecodeArr(&this.ArrFloat64) 453 | r.DecodeArr(&this.ArrComplex64) 454 | r.DecodeArr(&this.ArrComplex128) 455 | r.DecodeArr(&this.ArrTime) 456 | r.DecodeArr(&this.ArrAny) 457 | r.DecodeArr(&this.ArrNo) 458 | r.DecodeMap(&this.MapStringInt) 459 | r.DecodeMap(&this.MapStringUint) 460 | r.DecodeMap(&this.MapStringBool) 461 | r.DecodeMap(&this.MapStringString) 462 | r.DecodeMap(&this.MapIntAny) 463 | r.DecodeMap(&this.MapUintAny) 464 | r.DecodeMap(&this.MapStringAny) 465 | r.DecodeMap(&this.MapTimeAny) 466 | r.DecodeMap(&this.MapAnyAny) 467 | r.DecodeMap(&this.MapNo) 468 | return 469 | } 470 | 471 | // ---------------------------------------------------------------------- 472 | 473 | var str = "This is the very last time that I should have to test this" 474 | 475 | var bin = []byte{ 476 | 84, 104, 105, 115, 32, 105, 115, 32, 116, 104, 101, 32, 118, 101, 477 | 114, 121, 32, 108, 97, 115, 116, 32, 116, 105, 109, 101, 32, 116, 478 | 104, 97, 116, 32, 73, 32, 115, 104, 111, 117, 108, 100, 32, 104, 97, 479 | 118, 101, 32, 116, 111, 32, 116, 101, 115, 116, 32, 116, 104, 105, 115, 480 | } 481 | 482 | var lng = append(bin, append(bin, append(bin, append(bin, bin...)...)...)...) 483 | 484 | // ---------------------------------------------------------------------- 485 | // ---------------------------------------------------------------------- 486 | // ---------------------------------------------------------------------- 487 | // ---------------------------------------------------------------------- 488 | // ---------------------------------------------------------------------- 489 | 490 | func init() { 491 | Register(&Simple{}) 492 | Register(&Corked{}) 493 | Register(&Selfed{}) 494 | Register(&Complex{}) 495 | } 496 | 497 | func TestGeneral(t *testing.T) { 498 | 499 | tme, _ := time.Parse(time.RFC3339, "1987-06-22T08:00:00.123456789Z") 500 | 501 | Convey("nil will encode and decode", t, func() { 502 | var tmp interface{} 503 | var val = interface{}(nil) 504 | var bit = []byte{cNil} 505 | var enc = Encode(val) 506 | var dec = Decode(bit) 507 | DecodeInto(bit, &tmp) 508 | So(enc, ShouldResemble, bit) 509 | So(tmp, ShouldResemble, val) 510 | So(dec, ShouldResemble, val) 511 | }) 512 | 513 | Convey("true will encode and decode", t, func() { 514 | var tmp bool 515 | var val = true 516 | var bit = []byte{cTrue} 517 | var enc = Encode(val) 518 | var dec = Decode(bit) 519 | DecodeInto(bit, &tmp) 520 | So(enc, ShouldResemble, bit) 521 | So(tmp, ShouldResemble, val) 522 | So(dec, ShouldResemble, val) 523 | }) 524 | 525 | Convey("false will encode and decode", t, func() { 526 | var tmp bool 527 | var val = false 528 | var bit = []byte{cFalse} 529 | var enc = Encode(val) 530 | var dec = Decode(bit) 531 | DecodeInto(bit, &tmp) 532 | So(enc, ShouldResemble, bit) 533 | So(tmp, ShouldResemble, val) 534 | So(dec, ShouldResemble, val) 535 | }) 536 | 537 | Convey("byte will encode and decode", t, func() { 538 | var tmp byte 539 | var val = byte('a') 540 | var bit = []byte{97} 541 | var oth = int(97) 542 | var enc = Encode(val) 543 | var dec = Decode(bit) 544 | DecodeInto(bit, &tmp) 545 | So(enc, ShouldResemble, bit) 546 | So(tmp, ShouldResemble, val) 547 | So(dec, ShouldResemble, oth) 548 | }) 549 | 550 | Convey("string will encode and decode", t, func() { 551 | var tmp string 552 | var val = "Hello" 553 | var bit = []byte{cFixStr + 0x05, 72, 101, 108, 108, 111} 554 | var enc = Encode(val) 555 | var dec = Decode(bit) 556 | DecodeInto(bit, &tmp) 557 | So(enc, ShouldResemble, bit) 558 | So(tmp, ShouldResemble, val) 559 | So(dec, ShouldResemble, val) 560 | }) 561 | 562 | Convey("string8 will encode and decode", t, func() { 563 | var tmp string 564 | var val = str 565 | var bit = append([]byte{cStr8, 58}, bin...) 566 | var enc = Encode(val) 567 | var dec = Decode(bit) 568 | DecodeInto(bit, &tmp) 569 | So(enc, ShouldResemble, bit) 570 | So(tmp, ShouldResemble, val) 571 | So(dec, ShouldResemble, val) 572 | }) 573 | 574 | Convey("string16 will encode and decode", t, func() { 575 | var tmp string 576 | var val = str + str + str + str + str 577 | var bit = append([]byte{cStr16, 1, 34}, lng...) 578 | var enc = Encode(val) 579 | var dec = Decode(bit) 580 | DecodeInto(bit, &tmp) 581 | So(enc, ShouldResemble, bit) 582 | So(tmp, ShouldResemble, val) 583 | So(dec, ShouldResemble, val) 584 | }) 585 | 586 | Convey("[]byte will encode and decode", t, func() { 587 | var tmp []byte 588 | var val = []byte{72, 101, 108, 108, 111} 589 | var bit = []byte{cFixBin + 0x05, 72, 101, 108, 108, 111} 590 | var enc = Encode(val) 591 | var dec = Decode(bit) 592 | DecodeInto(bit, &tmp) 593 | So(enc, ShouldResemble, bit) 594 | So(tmp, ShouldResemble, val) 595 | So(dec, ShouldResemble, val) 596 | }) 597 | 598 | Convey("[]byte8 will encode and decode", t, func() { 599 | var tmp []byte 600 | var val = bin 601 | var bit = append([]byte{cBin8, 58}, bin...) 602 | var enc = Encode(val) 603 | var dec = Decode(bit) 604 | DecodeInto(bit, &tmp) 605 | So(enc, ShouldResemble, bit) 606 | So(tmp, ShouldResemble, val) 607 | So(dec, ShouldResemble, val) 608 | }) 609 | 610 | Convey("[]byte16 will encode and decode", t, func() { 611 | var tmp []byte 612 | var val = lng 613 | var bit = append([]byte{cBin16, 1, 34}, lng...) 614 | var enc = Encode(val) 615 | var dec = Decode(bit) 616 | DecodeInto(bit, &tmp) 617 | So(enc, ShouldResemble, bit) 618 | So(tmp, ShouldResemble, val) 619 | So(dec, ShouldResemble, val) 620 | }) 621 | 622 | Convey("int will encode and decode", t, func() { 623 | var tmp int 624 | var val = int(1) 625 | var bit = []byte{1} 626 | var enc = Encode(val) 627 | var dec = Decode(bit) 628 | DecodeInto(bit, &tmp) 629 | So(enc, ShouldResemble, bit) 630 | So(tmp, ShouldResemble, val) 631 | So(dec, ShouldResemble, val) 632 | }) 633 | 634 | Convey("int8 will encode and decode", t, func() { 635 | var tmp int8 636 | var val = int8(math.MaxInt8) 637 | var bit = []byte{127} 638 | var enc = Encode(val) 639 | var dec = Decode(bit) 640 | DecodeInto(bit, &tmp) 641 | So(enc, ShouldResemble, bit) 642 | So(tmp, ShouldResemble, val) 643 | So(dec, ShouldResemble, int(val)) 644 | }) 645 | 646 | Convey("int16 will encode and decode", t, func() { 647 | var tmp int16 648 | var val = int16(math.MaxInt16) 649 | var bit = []byte{cInt16, 127, 255} 650 | var enc = Encode(val) 651 | var dec = Decode(bit) 652 | DecodeInto(bit, &tmp) 653 | So(enc, ShouldResemble, bit) 654 | So(tmp, ShouldResemble, val) 655 | So(dec, ShouldResemble, int(val)) 656 | }) 657 | 658 | Convey("int32 will encode and decode", t, func() { 659 | var tmp int32 660 | var val = int32(math.MaxInt32) 661 | var bit = []byte{cInt32, 127, 255, 255, 255} 662 | var enc = Encode(val) 663 | var dec = Decode(bit) 664 | DecodeInto(bit, &tmp) 665 | So(enc, ShouldResemble, bit) 666 | So(tmp, ShouldResemble, val) 667 | So(dec, ShouldResemble, int(val)) 668 | }) 669 | 670 | Convey("int64 will encode and decode", t, func() { 671 | var tmp int64 672 | var val = int64(math.MaxInt64) 673 | var bit = []byte{cInt64, 127, 255, 255, 255, 255, 255, 255, 255} 674 | var enc = Encode(val) 675 | var dec = Decode(bit) 676 | DecodeInto(bit, &tmp) 677 | So(enc, ShouldResemble, bit) 678 | So(tmp, ShouldResemble, val) 679 | So(dec, ShouldResemble, int(val)) 680 | }) 681 | 682 | Convey("uint will encode and decode", t, func() { 683 | var tmp uint 684 | var val = uint(1) 685 | var bit = []byte{1} 686 | var enc = Encode(val) 687 | var dec = Decode(bit) 688 | DecodeInto(bit, &tmp) 689 | So(enc, ShouldResemble, bit) 690 | So(tmp, ShouldResemble, val) 691 | So(dec, ShouldResemble, int(val)) 692 | }) 693 | 694 | Convey("uint16 will encode and decode", t, func() { 695 | var tmp uint16 696 | var val = uint16(math.MaxUint16) 697 | var bit = []byte{cUint16, 255, 255} 698 | var enc = Encode(val) 699 | var dec = Decode(bit) 700 | DecodeInto(bit, &tmp) 701 | So(enc, ShouldResemble, bit) 702 | So(tmp, ShouldResemble, val) 703 | So(dec, ShouldResemble, uint(val)) 704 | }) 705 | 706 | Convey("uint32 will encode and decode", t, func() { 707 | var tmp uint32 708 | var val = uint32(math.MaxUint32) 709 | var bit = []byte{cUint32, 255, 255, 255, 255} 710 | var enc = Encode(val) 711 | var dec = Decode(bit) 712 | DecodeInto(bit, &tmp) 713 | So(enc, ShouldResemble, bit) 714 | So(tmp, ShouldResemble, val) 715 | So(dec, ShouldResemble, uint(val)) 716 | }) 717 | 718 | Convey("uint64 will encode and decode", t, func() { 719 | var tmp uint64 720 | var val = uint64(math.MaxUint64) 721 | var bit = []byte{cUint64, 255, 255, 255, 255, 255, 255, 255, 255} 722 | var enc = Encode(val) 723 | var dec = Decode(bit) 724 | DecodeInto(bit, &tmp) 725 | So(enc, ShouldResemble, bit) 726 | So(tmp, ShouldResemble, val) 727 | So(dec, ShouldResemble, uint(val)) 728 | }) 729 | 730 | Convey("float32 will encode and decode", t, func() { 731 | var tmp float32 732 | var val = float32(math.Pi) 733 | var bit = []byte{cFloat32, 64, 73, 15, 219} 734 | var enc = Encode(val) 735 | var dec = Decode(bit) 736 | DecodeInto(bit, &tmp) 737 | So(enc, ShouldResemble, bit) 738 | So(tmp, ShouldResemble, val) 739 | So(dec, ShouldResemble, val) 740 | }) 741 | 742 | Convey("float32 will encode and decode into float64", t, func() { 743 | var tmp float64 744 | var val = float32(math.Pi) 745 | var gen = float64(float32(math.Pi)) 746 | var bit = []byte{cFloat32, 64, 73, 15, 219} 747 | var enc = Encode(val) 748 | var dec = Decode(bit) 749 | DecodeInto(bit, &tmp) 750 | So(enc, ShouldResemble, bit) 751 | So(tmp, ShouldResemble, gen) 752 | So(dec, ShouldResemble, val) 753 | }) 754 | 755 | Convey("float64 will encode and decode", t, func() { 756 | var tmp float64 757 | var val = float64(math.Pi) 758 | var bit = []byte{cFloat64, 64, 9, 33, 251, 84, 68, 45, 24} 759 | var enc = Encode(val) 760 | var dec = Decode(bit) 761 | DecodeInto(bit, &tmp) 762 | So(enc, ShouldResemble, bit) 763 | So(tmp, ShouldResemble, val) 764 | So(dec, ShouldResemble, val) 765 | }) 766 | 767 | Convey("complex64 will encode and decode", t, func() { 768 | var tmp complex64 769 | var val = complex64(math.Pi) 770 | var bit = []byte{cComplex64, 64, 73, 15, 219, 0, 0, 0, 0} 771 | var enc = Encode(val) 772 | var dec = Decode(bit) 773 | DecodeInto(bit, &tmp) 774 | So(enc, ShouldResemble, bit) 775 | So(tmp, ShouldResemble, val) 776 | So(dec, ShouldResemble, val) 777 | }) 778 | 779 | Convey("complex128 will encode and decode", t, func() { 780 | var tmp complex128 781 | var val = complex128(math.Pi) 782 | var bit = []byte{cComplex128, 64, 9, 33, 251, 84, 68, 45, 24, 0, 0, 0, 0, 0, 0, 0, 0} 783 | var enc = Encode(val) 784 | var dec = Decode(bit) 785 | DecodeInto(bit, &tmp) 786 | So(enc, ShouldResemble, bit) 787 | So(tmp, ShouldResemble, val) 788 | So(dec, ShouldResemble, val) 789 | }) 790 | 791 | Convey("time.Time will encode and decode", t, func() { 792 | var tmp time.Time 793 | var val = tme 794 | var bit = []byte{cTime, 7, 166, 199, 91, 123, 67, 205, 21} 795 | var enc = Encode(val) 796 | var dec = Decode(bit) 797 | DecodeInto(bit, &tmp) 798 | So(enc, ShouldResemble, bit) 799 | So(tmp, ShouldResemble, val) 800 | So(dec, ShouldResemble, val) 801 | }) 802 | 803 | Convey("CustomInt will encode and decode", t, func() { 804 | var tmp CustomInt 805 | var val = CustomInt(666) 806 | var gen = int(666) 807 | var bit = []byte{cInt16, 2, 154} 808 | var enc = Encode(val) 809 | var dec = Decode(bit) 810 | DecodeInto(bit, &tmp) 811 | So(enc, ShouldResemble, bit) 812 | So(tmp, ShouldResemble, val) 813 | So(dec, ShouldResemble, gen) 814 | }) 815 | 816 | Convey("CustomString will encode and decode", t, func() { 817 | var tmp CustomString 818 | var val = CustomString("Hello") 819 | var gen = "Hello" 820 | var bit = []byte{cFixStr + 0x05, 72, 101, 108, 108, 111} 821 | var enc = Encode(val) 822 | var dec = Decode(bit) 823 | DecodeInto(bit, &tmp) 824 | So(enc, ShouldResemble, bit) 825 | So(tmp, ShouldResemble, val) 826 | So(dec, ShouldResemble, gen) 827 | }) 828 | 829 | Convey("Tested will encode and decode", t, func() { 830 | var tmp Tested 831 | var val = Tested{"test", []byte("test"), []string{"1", "2"}, map[string]string{"1": "2"}, false, 25, "Omitted", ""} 832 | var oth = Tested{"test", []byte("test"), []string{"1", "2"}, map[string]string{"1": "2"}, false, 25, "", ""} 833 | var gen = map[interface{}]interface{}{"Name": "test", "data": []byte("test"), "Temp": []interface{}{"1", "2"}, "Test": map[interface{}]interface{}{"1": "2"}, "Count": int(25)} 834 | var bit = []byte{cFixMap + 0x05, /**/ 835 | cFixStr + 0x04, 78, 97, 109, 101, cFixStr + 0x04, 116, 101, 115, 116, /**/ 836 | cFixStr + 0x04, 100, 97, 116, 97, cFixBin + 0x04, 116, 101, 115, 116, /**/ 837 | cFixStr + 0x04, 84, 101, 109, 112, cFixArr + 0x02, 129, 49, 129, 50, /**/ 838 | cFixStr + 0x04, 84, 101, 115, 116, cFixMap + 0x01, 129, 49, 129, 50, /**/ 839 | cFixStr + 0x05, 67, 111, 117, 110, 116 /**/, 25, 840 | } 841 | var enc = Encode(val) 842 | var dec = Decode(bit) 843 | DecodeInto(bit, &tmp) 844 | So(enc, ShouldResemble, bit) 845 | So(tmp, ShouldResemble, oth) 846 | So(dec, ShouldResemble, gen) 847 | }) 848 | 849 | Convey("*Tested will encode and decode", t, func() { 850 | var tmp Tested 851 | var val = Tested{"test", []byte("test"), []string{"1", "2"}, map[string]string{"1": "2"}, false, 25, "Omitted", ""} 852 | var oth = Tested{"test", []byte("test"), []string{"1", "2"}, map[string]string{"1": "2"}, false, 25, "", ""} 853 | var gen = map[interface{}]interface{}{"Name": "test", "data": []byte("test"), "Temp": []interface{}{"1", "2"}, "Test": map[interface{}]interface{}{"1": "2"}, "Count": int(25)} 854 | var bit = []byte{cFixMap + 0x05, /**/ 855 | cFixStr + 0x04, 78, 97, 109, 101, cFixStr + 0x04, 116, 101, 115, 116, /**/ 856 | cFixStr + 0x04, 100, 97, 116, 97, cFixBin + 0x04, 116, 101, 115, 116, /**/ 857 | cFixStr + 0x04, 84, 101, 109, 112, cFixArr + 0x02, 129, 49, 129, 50, /**/ 858 | cFixStr + 0x04, 84, 101, 115, 116, cFixMap + 0x01, 129, 49, 129, 50, /**/ 859 | cFixStr + 0x05, 67, 111, 117, 110, 116 /**/, 25, 860 | } 861 | var enc = Encode(val) 862 | var dec = Decode(bit) 863 | DecodeInto(bit, &tmp) 864 | So(enc, ShouldResemble, bit) 865 | So(tmp, ShouldResemble, oth) 866 | So(dec, ShouldResemble, gen) 867 | }) 868 | 869 | Convey("*Errord will not encode and decode", t, func() { 870 | var tmp Errord 871 | var val = &Errord{} 872 | var bit = []byte{cFixExt + 0x00} 873 | eer := NewEncoder(bytes.NewBuffer(nil)).Encode(val) 874 | der := NewDecoder(bytes.NewReader(bit)).Decode(&tmp) 875 | So(eer, ShouldNotBeNil) 876 | So(der, ShouldNotBeNil) 877 | }) 878 | 879 | Convey("*Simple will encode and decode", t, func() { 880 | var tmp Simple 881 | var val = &Simple{} 882 | var gen = *val 883 | var bit = []byte{cFixExt, 0x01} 884 | var enc = Encode(val) 885 | var dec = Decode(bit) 886 | DecodeInto(bit, &tmp) 887 | So(enc, ShouldResemble, bit) 888 | So(tmp, ShouldResemble, gen) 889 | So(dec, ShouldResemble, val) 890 | }) 891 | 892 | Convey("*Corked will encode and decode", t, func() { 893 | var tmp Corked 894 | var val = &Corked{"test", []byte("test"), []string{"1", "2"}, map[string]string{"1": "2"}, false, 25, "", ""} 895 | var gen = *val 896 | var bit = []byte{cExt8, 0x15, 0x02, /**/ 897 | cFixStr + 0x04, 116, 101, 115, 116, /**/ 898 | cFixBin + 0x04, 116, 101, 115, 116, /**/ 899 | cFixArr + 0x02, 129, 49, 129, 50, /**/ 900 | cFixMap + 0x01, 129, 49, 129, 50, /**/ 901 | 25, 902 | } 903 | var enc = Encode(val) 904 | var dec = Decode(bit) 905 | DecodeInto(bit, &tmp) 906 | So(enc, ShouldResemble, bit) 907 | So(tmp, ShouldResemble, gen) 908 | So(dec, ShouldResemble, val) 909 | }) 910 | 911 | Convey("*Selfed will encode and decode", t, func() { 912 | var tmp Selfed 913 | var val = &Selfed{"test", []byte("test"), []string{"1", "2"}, map[string]string{"1": "2"}, false, 25, "", ""} 914 | var gen = *val 915 | var bit = []byte{cSlf, 0x03, /**/ 916 | cFixStr + 0x04, 116, 101, 115, 116, /**/ 917 | cFixBin + 0x04, 116, 101, 115, 116, /**/ 918 | cFixArr + 0x02, 129, 49, 129, 50, /**/ 919 | cFixMap + 0x01, 129, 49, 129, 50, /**/ 920 | 25, 921 | } 922 | var enc = Encode(val) 923 | var dec = Decode(bit) 924 | DecodeInto(bit, &tmp) 925 | So(enc, ShouldResemble, bit) 926 | So(tmp, ShouldResemble, gen) 927 | So(dec, ShouldResemble, val) 928 | }) 929 | 930 | Convey("[]bool will encode and decode", t, func() { 931 | var tmp []bool 932 | var val = []bool{true, false} 933 | var gen = []interface{}{true, false} 934 | var bit = []byte{cFixArr + 0x02, cTrue, cFalse} 935 | var enc = Encode(val) 936 | var dec = Decode(bit) 937 | DecodeInto(bit, &tmp) 938 | So(enc, ShouldResemble, bit) 939 | So(tmp, ShouldResemble, val) 940 | So(dec, ShouldResemble, gen) 941 | }) 942 | 943 | Convey("[]string will encode and decode", t, func() { 944 | var tmp []string 945 | var val = []string{"Hello", "World"} 946 | var gen = []interface{}{"Hello", "World"} 947 | var bit = []byte{cFixArr + 0x02 /**/, cFixStr + 0x05, 72, 101, 108, 108, 111 /**/, cFixStr + 0x05, 87, 111, 114, 108, 100} 948 | var enc = Encode(val) 949 | var dec = Decode(bit) 950 | DecodeInto(bit, &tmp) 951 | So(enc, ShouldResemble, bit) 952 | So(tmp, ShouldResemble, val) 953 | So(dec, ShouldResemble, gen) 954 | }) 955 | 956 | Convey("[]int will encode and decode", t, func() { 957 | var tmp []int 958 | var val = []int{0, 1, math.MaxInt8, math.MaxInt16, math.MaxInt32, math.MaxInt64} 959 | var gen = []interface{}{0, 1, math.MaxInt8, math.MaxInt16, math.MaxInt32, math.MaxInt64} 960 | var bit = []byte{cFixArr + 0x06 /**/, 0 /**/, 1 /**/, 127 /**/, cInt16, 127, 255 /**/, cInt32, 127, 255, 255, 255 /**/, cInt64, 127, 255, 255, 255, 255, 255, 255, 255} 961 | var enc = Encode(val) 962 | var dec = Decode(bit) 963 | DecodeInto(bit, &tmp) 964 | So(enc, ShouldResemble, bit) 965 | So(tmp, ShouldResemble, val) 966 | So(dec, ShouldResemble, gen) 967 | }) 968 | 969 | Convey("[]int8 will encode and decode", t, func() { 970 | var tmp []int8 971 | var val = []int8{1, math.MaxInt8} 972 | var gen = []interface{}{1, math.MaxInt8} 973 | var bit = []byte{cFixArr + 0x02 /**/, 1 /**/, 127} 974 | var enc = Encode(val) 975 | var dec = Decode(bit) 976 | DecodeInto(bit, &tmp) 977 | So(enc, ShouldResemble, bit) 978 | So(tmp, ShouldResemble, val) 979 | So(dec, ShouldResemble, gen) 980 | }) 981 | 982 | Convey("[]int16 will encode and decode", t, func() { 983 | var tmp []int16 984 | var val = []int16{1, math.MaxInt8, math.MaxInt16} 985 | var gen = []interface{}{1, math.MaxInt8, math.MaxInt16} 986 | var bit = []byte{cFixArr + 0x03 /**/, 1 /**/, 127 /**/, cInt16, 127, 255} 987 | var enc = Encode(val) 988 | var dec = Decode(bit) 989 | DecodeInto(bit, &tmp) 990 | So(enc, ShouldResemble, bit) 991 | So(tmp, ShouldResemble, val) 992 | So(dec, ShouldResemble, gen) 993 | }) 994 | 995 | Convey("[]int32 will encode and decode", t, func() { 996 | var tmp []int32 997 | var val = []int32{1, math.MaxInt8, math.MaxInt16, math.MaxInt32} 998 | var gen = []interface{}{1, math.MaxInt8, math.MaxInt16, math.MaxInt32} 999 | var bit = []byte{cFixArr + 0x04 /**/, 1 /**/, 127 /**/, cInt16, 127, 255 /**/, cInt32, 127, 255, 255, 255} 1000 | var enc = Encode(val) 1001 | var dec = Decode(bit) 1002 | DecodeInto(bit, &tmp) 1003 | So(enc, ShouldResemble, bit) 1004 | So(tmp, ShouldResemble, val) 1005 | So(dec, ShouldResemble, gen) 1006 | }) 1007 | 1008 | Convey("[]int64 will encode and decode", t, func() { 1009 | var tmp []int64 1010 | var val = []int64{1, math.MaxInt8, math.MaxInt16, math.MaxInt32, math.MaxInt64} 1011 | var gen = []interface{}{1, math.MaxInt8, math.MaxInt16, math.MaxInt32, math.MaxInt64} 1012 | var bit = []byte{cFixArr + 0x05 /**/, 1 /**/, 127 /**/, cInt16, 127, 255 /**/, cInt32, 127, 255, 255, 255 /**/, cInt64, 127, 255, 255, 255, 255, 255, 255, 255} 1013 | var enc = Encode(val) 1014 | var dec = Decode(bit) 1015 | DecodeInto(bit, &tmp) 1016 | So(enc, ShouldResemble, bit) 1017 | So(tmp, ShouldResemble, val) 1018 | So(dec, ShouldResemble, gen) 1019 | }) 1020 | 1021 | Convey("[]uint will encode and decode", t, func() { 1022 | var tmp []uint 1023 | var val = []uint{0, 1, math.MaxUint8, math.MaxUint16, math.MaxUint32, math.MaxUint64} 1024 | var gen = []interface{}{int(0), int(1), uint(math.MaxUint8), uint(math.MaxUint16), uint(math.MaxUint32), uint(math.MaxUint64)} 1025 | var bit = []byte{cFixArr + 0x06 /**/, 0 /**/, 1, cUint8, 255 /**/, cUint16, 255, 255 /**/, cUint32, 255, 255, 255, 255 /**/, cUint64, 255, 255, 255, 255, 255, 255, 255, 255} 1026 | var enc = Encode(val) 1027 | var dec = Decode(bit) 1028 | DecodeInto(bit, &tmp) 1029 | So(enc, ShouldResemble, bit) 1030 | So(tmp, ShouldResemble, val) 1031 | So(dec, ShouldResemble, gen) 1032 | }) 1033 | 1034 | Convey("[]uint16 will encode and decode", t, func() { 1035 | var tmp []uint16 1036 | var val = []uint16{1, math.MaxUint8, math.MaxUint16} 1037 | var gen = []interface{}{int(1), uint(math.MaxUint8), uint(math.MaxUint16)} 1038 | var bit = []byte{cFixArr + 0x03 /**/, 1 /**/, cUint8, 255 /**/, cUint16, 255, 255} 1039 | var enc = Encode(val) 1040 | var dec = Decode(bit) 1041 | DecodeInto(bit, &tmp) 1042 | So(enc, ShouldResemble, bit) 1043 | So(tmp, ShouldResemble, val) 1044 | So(dec, ShouldResemble, gen) 1045 | }) 1046 | 1047 | Convey("[]uint32 will encode and decode", t, func() { 1048 | var tmp []uint32 1049 | var val = []uint32{1, math.MaxUint8, math.MaxUint16, math.MaxUint32} 1050 | var gen = []interface{}{int(1), uint(math.MaxUint8), uint(math.MaxUint16), uint(math.MaxUint32)} 1051 | var bit = []byte{cFixArr + 0x04 /**/, 1 /**/, cUint8, 255 /**/, cUint16, 255, 255 /**/, cUint32, 255, 255, 255, 255} 1052 | var enc = Encode(val) 1053 | var dec = Decode(bit) 1054 | DecodeInto(bit, &tmp) 1055 | So(enc, ShouldResemble, bit) 1056 | So(tmp, ShouldResemble, val) 1057 | So(dec, ShouldResemble, gen) 1058 | }) 1059 | 1060 | Convey("[]uint64 will encode and decode", t, func() { 1061 | var tmp []uint64 1062 | var val = []uint64{1, math.MaxUint8, math.MaxUint16, math.MaxUint32, math.MaxUint64} 1063 | var gen = []interface{}{int(1), uint(math.MaxUint8), uint(math.MaxUint16), uint(math.MaxUint32), uint(math.MaxUint64)} 1064 | var bit = []byte{cFixArr + 0x05 /**/, 1 /**/, cUint8, 255 /**/, cUint16, 255, 255 /**/, cUint32, 255, 255, 255, 255 /**/, cUint64, 255, 255, 255, 255, 255, 255, 255, 255} 1065 | var enc = Encode(val) 1066 | var dec = Decode(bit) 1067 | DecodeInto(bit, &tmp) 1068 | So(enc, ShouldResemble, bit) 1069 | So(tmp, ShouldResemble, val) 1070 | So(dec, ShouldResemble, gen) 1071 | }) 1072 | 1073 | Convey("[]float32 will encode and decode", t, func() { 1074 | var tmp []float32 1075 | var val = []float32{math.Pi, math.Pi} 1076 | var gen = []interface{}{float32(math.Pi), float32(math.Pi)} 1077 | var bit = []byte{cFixArr + 0x02 /**/, cFloat32, 64, 73, 15, 219 /**/, cFloat32, 64, 73, 15, 219} 1078 | var enc = Encode(val) 1079 | var dec = Decode(bit) 1080 | DecodeInto(bit, &tmp) 1081 | So(enc, ShouldResemble, bit) 1082 | So(tmp, ShouldResemble, val) 1083 | So(dec, ShouldResemble, gen) 1084 | }) 1085 | 1086 | Convey("[]float64 will encode and decode", t, func() { 1087 | var tmp []float64 1088 | var val = []float64{math.Pi, math.Pi} 1089 | var gen = []interface{}{float64(math.Pi), float64(math.Pi)} 1090 | var bit = []byte{cFixArr + 0x02 /**/, cFloat64, 64, 9, 33, 251, 84, 68, 45, 24 /**/, cFloat64, 64, 9, 33, 251, 84, 68, 45, 24} 1091 | var enc = Encode(val) 1092 | var dec = Decode(bit) 1093 | DecodeInto(bit, &tmp) 1094 | So(enc, ShouldResemble, bit) 1095 | So(tmp, ShouldResemble, val) 1096 | So(dec, ShouldResemble, gen) 1097 | }) 1098 | 1099 | Convey("[]complex64 will encode and decode", t, func() { 1100 | var tmp []complex64 1101 | var val = []complex64{math.Pi, math.Pi} 1102 | var gen = []interface{}{complex64(math.Pi), complex64(math.Pi)} 1103 | var bit = []byte{cFixArr + 0x02 /**/, cComplex64, 64, 73, 15, 219, 0, 0, 0, 0 /**/, cComplex64, 64, 73, 15, 219, 0, 0, 0, 0} 1104 | var enc = Encode(val) 1105 | var dec = Decode(bit) 1106 | DecodeInto(bit, &tmp) 1107 | So(enc, ShouldResemble, bit) 1108 | So(tmp, ShouldResemble, val) 1109 | So(dec, ShouldResemble, gen) 1110 | }) 1111 | 1112 | Convey("[]complex128 will encode and decode", t, func() { 1113 | var tmp []complex128 1114 | var val = []complex128{math.Pi, math.Pi} 1115 | var gen = []interface{}{complex128(math.Pi), complex128(math.Pi)} 1116 | var bit = []byte{cFixArr + 0x02 /**/, cComplex128, 64, 9, 33, 251, 84, 68, 45, 24, 0, 0, 0, 0, 0, 0, 0, 0 /**/, cComplex128, 64, 9, 33, 251, 84, 68, 45, 24, 0, 0, 0, 0, 0, 0, 0, 0} 1117 | var enc = Encode(val) 1118 | var dec = Decode(bit) 1119 | DecodeInto(bit, &tmp) 1120 | So(enc, ShouldResemble, bit) 1121 | So(tmp, ShouldResemble, val) 1122 | So(dec, ShouldResemble, gen) 1123 | }) 1124 | 1125 | Convey("[]time.Time will encode and decode", t, func() { 1126 | var tmp []time.Time 1127 | var val = []time.Time{tme, tme} 1128 | var gen = []interface{}{tme, tme} 1129 | var bit = []byte{cFixArr + 0x02 /**/, cTime, 7, 166, 199, 91, 123, 67, 205, 21 /**/, cTime, 7, 166, 199, 91, 123, 67, 205, 21} 1130 | var enc = Encode(val) 1131 | var dec = Decode(bit) 1132 | DecodeInto(bit, &tmp) 1133 | So(enc, ShouldResemble, bit) 1134 | So(tmp, ShouldResemble, val) 1135 | So(dec, ShouldResemble, gen) 1136 | }) 1137 | 1138 | Convey("[]interface{} will encode and decode", t, func() { 1139 | var tmp []interface{} 1140 | var val = []interface{}{nil, true, false, "test", []byte("test"), int8(77), uint16(177), float64(math.Pi)} 1141 | var gen = []interface{}{nil, true, false, "test", []byte("test"), int(77), uint(177), float64(math.Pi)} 1142 | var bit = []byte{cFixArr + 0x08 /**/, cNil, cTrue, cFalse /**/, cFixStr + 0x04, 116, 101, 115, 116 /**/, cFixBin + 0x04, 116, 101, 115, 116 /**/, 77 /**/, cUint8, 177 /**/, cFloat64, 64, 9, 33, 251, 84, 68, 45, 24} 1143 | var enc = Encode(val) 1144 | var dec = Decode(bit) 1145 | DecodeInto(bit, &tmp) 1146 | So(enc, ShouldResemble, bit) 1147 | So(tmp, ShouldResemble, gen) 1148 | So(dec, ShouldResemble, gen) 1149 | }) 1150 | 1151 | Convey("[]interface{} will encode and decode", t, func() { 1152 | var tmp []interface{} 1153 | var val = [][][]float64{{{math.Pi}}, {{math.Pi}}} 1154 | var gen = []interface{}{[]interface{}{[]interface{}{math.Pi}}, []interface{}{[]interface{}{math.Pi}}} 1155 | var bit = []byte{cFixArr + 0x02 /**/, cFixArr + 0x01, cFixArr + 0x01, cFloat64, 64, 9, 33, 251, 84, 68, 45, 24 /**/, cFixArr + 0x01, cFixArr + 0x01, cFloat64, 64, 9, 33, 251, 84, 68, 45, 24} 1156 | var enc = Encode(val) 1157 | var dec = Decode(bit) 1158 | DecodeInto(bit, &tmp) 1159 | So(enc, ShouldResemble, bit) 1160 | So(tmp, ShouldResemble, gen) 1161 | So(dec, ShouldResemble, gen) 1162 | }) 1163 | 1164 | Convey("map[string]bool will encode and decode", t, func() { 1165 | var tmp map[string]bool 1166 | var val = map[string]bool{"test": true} 1167 | var gen = map[interface{}]interface{}{"test": true} 1168 | var bit = []byte{cFixMap + 0x01 /**/, cFixStr + 0x04, 116, 101, 115, 116, cTrue} 1169 | var enc = Encode(val) 1170 | var dec = Decode(bit) 1171 | DecodeInto(bit, &tmp) 1172 | So(enc, ShouldResemble, bit) 1173 | So(tmp, ShouldResemble, val) 1174 | So(dec, ShouldResemble, gen) 1175 | }) 1176 | 1177 | Convey("map[string]int will encode and decode", t, func() { 1178 | var tmp map[string]int 1179 | var val = map[string]int{"test": math.MaxInt32} 1180 | var gen = map[interface{}]interface{}{"test": math.MaxInt32} 1181 | var bit = []byte{cFixMap + 0x01 /**/, cFixStr + 0x04, 116, 101, 115, 116, cInt32, 127, 255, 255, 255} 1182 | var enc = Encode(val) 1183 | var dec = Decode(bit) 1184 | DecodeInto(bit, &tmp) 1185 | So(enc, ShouldResemble, bit) 1186 | So(tmp, ShouldResemble, val) 1187 | So(dec, ShouldResemble, gen) 1188 | }) 1189 | 1190 | Convey("map[string]uint will encode and decode", t, func() { 1191 | var tmp map[string]uint 1192 | var val = map[string]uint{"test": math.MaxUint32} 1193 | var gen = map[interface{}]interface{}{"test": uint(math.MaxUint32)} 1194 | var bit = []byte{cFixMap + 0x01 /**/, cFixStr + 0x04, 116, 101, 115, 116, cUint32, 255, 255, 255, 255} 1195 | var enc = Encode(val) 1196 | var dec = Decode(bit) 1197 | DecodeInto(bit, &tmp) 1198 | So(enc, ShouldResemble, bit) 1199 | So(tmp, ShouldResemble, val) 1200 | So(dec, ShouldResemble, gen) 1201 | }) 1202 | 1203 | Convey("map[string]string will encode and decode", t, func() { 1204 | var tmp map[string]string 1205 | var val = map[string]string{"test": "Hello"} 1206 | var gen = map[interface{}]interface{}{"test": "Hello"} 1207 | var bit = []byte{cFixMap + 0x01 /**/, cFixStr + 0x04, 116, 101, 115, 116, cFixStr + 0x05, 72, 101, 108, 108, 111} 1208 | var enc = Encode(val) 1209 | var dec = Decode(bit) 1210 | DecodeInto(bit, &tmp) 1211 | So(enc, ShouldResemble, bit) 1212 | So(tmp, ShouldResemble, val) 1213 | So(dec, ShouldResemble, gen) 1214 | }) 1215 | 1216 | Convey("map[int]interface{} will encode and decode", t, func() { 1217 | var tmp map[int]interface{} 1218 | var val = map[int]interface{}{math.MaxInt8: math.Pi} 1219 | var gen = map[interface{}]interface{}{int(math.MaxInt8): float64(math.Pi)} 1220 | var bit = []byte{cFixMap + 0x01 /**/, 127, cFloat64, 64, 9, 33, 251, 84, 68, 45, 24} 1221 | var enc = Encode(val) 1222 | var dec = Decode(bit) 1223 | DecodeInto(bit, &tmp) 1224 | So(enc, ShouldResemble, bit) 1225 | So(tmp, ShouldResemble, val) 1226 | So(dec, ShouldResemble, gen) 1227 | }) 1228 | 1229 | Convey("map[uint]interface{} will encode and decode", t, func() { 1230 | var tmp map[uint]interface{} 1231 | var val = map[uint]interface{}{math.MaxUint8: math.Pi} 1232 | var gen = map[interface{}]interface{}{uint(math.MaxUint8): float64(math.Pi)} 1233 | var bit = []byte{cFixMap + 0x01 /**/, cUint8, 255, cFloat64, 64, 9, 33, 251, 84, 68, 45, 24} 1234 | var enc = Encode(val) 1235 | var dec = Decode(bit) 1236 | DecodeInto(bit, &tmp) 1237 | So(enc, ShouldResemble, bit) 1238 | So(tmp, ShouldResemble, val) 1239 | So(dec, ShouldResemble, gen) 1240 | }) 1241 | 1242 | Convey("map[string]interface{} will encode and decode", t, func() { 1243 | var tmp map[string]interface{} 1244 | var val = map[string]interface{}{"test": math.Pi} 1245 | var gen = map[interface{}]interface{}{"test": math.Pi} 1246 | var bit = []byte{cFixMap + 0x01 /**/, cFixStr + 0x04, 116, 101, 115, 116, cFloat64, 64, 9, 33, 251, 84, 68, 45, 24} 1247 | var enc = Encode(val) 1248 | var dec = Decode(bit) 1249 | DecodeInto(bit, &tmp) 1250 | So(enc, ShouldResemble, bit) 1251 | So(tmp, ShouldResemble, val) 1252 | So(dec, ShouldResemble, gen) 1253 | }) 1254 | 1255 | Convey("map[time.Time]interface{} will encode and decode", t, func() { 1256 | var tmp map[time.Time]interface{} 1257 | var val = map[time.Time]interface{}{tme: math.Pi} 1258 | var gen = map[interface{}]interface{}{tme: math.Pi} 1259 | var bit = []byte{cFixMap + 0x01 /**/, cTime, 7, 166, 199, 91, 123, 67, 205, 21, cFloat64, 64, 9, 33, 251, 84, 68, 45, 24} 1260 | var enc = Encode(val) 1261 | var dec = Decode(bit) 1262 | DecodeInto(bit, &tmp) 1263 | So(enc, ShouldResemble, bit) 1264 | So(tmp, ShouldResemble, val) 1265 | So(dec, ShouldResemble, gen) 1266 | }) 1267 | 1268 | Convey("map[interface{}]interface{} will encode and decode", t, func() { 1269 | var tmp map[interface{}]interface{} 1270 | var val = map[interface{}]interface{}{"test": math.Pi} 1271 | var gen = map[interface{}]interface{}{"test": math.Pi} 1272 | var bit = []byte{cFixMap + 0x01 /**/, cFixStr + 0x04, 116, 101, 115, 116, cFloat64, 64, 9, 33, 251, 84, 68, 45, 24} 1273 | var enc = Encode(val) 1274 | var dec = Decode(bit) 1275 | DecodeInto(bit, &tmp) 1276 | So(enc, ShouldResemble, bit) 1277 | So(tmp, ShouldResemble, val) 1278 | So(dec, ShouldResemble, gen) 1279 | }) 1280 | 1281 | Convey("embedded map[string]interface{} will encode and decode", t, func() { 1282 | var tmp map[string]interface{} 1283 | var val = map[string]interface{}{"test": map[string]interface{}{"test": "Embedded"}} 1284 | var oth = map[string]interface{}{"test": map[interface{}]interface{}{"test": "Embedded"}} 1285 | var gen = map[interface{}]interface{}{"test": map[interface{}]interface{}{"test": "Embedded"}} 1286 | var bit = []byte{cFixMap + 0x01 /**/, cFixStr + 0x04, 116, 101, 115, 116 /**/, cFixMap + 0x01, cFixStr + 0x04, 116, 101, 115, 116, cFixStr + 0x08, 69, 109, 98, 101, 100, 100, 101, 100} 1287 | var enc = Encode(val) 1288 | var dec = Decode(bit) 1289 | DecodeInto(bit, &tmp) 1290 | So(enc, ShouldResemble, bit) 1291 | So(tmp, ShouldResemble, oth) 1292 | So(dec, ShouldResemble, gen) 1293 | }) 1294 | 1295 | Convey("CustomTextMarshaler will encode and decode", t, func() { 1296 | var tmp CustomTextMarshaler 1297 | var val = &CustomTextMarshaler{Field: "TEXT"} 1298 | var bit = []byte{cFixBin + 0x04, 84, 69, 88, 84} 1299 | var oth = []byte("TEXT") 1300 | var enc = Encode(val) 1301 | var dec = Decode(bit) 1302 | DecodeInto(bit, &tmp) 1303 | So(enc, ShouldResemble, bit) 1304 | So(&tmp, ShouldResemble, val) 1305 | So(dec, ShouldResemble, oth) 1306 | }) 1307 | 1308 | Convey("CustomBinaryMarshaler will encode and decode", t, func() { 1309 | var tmp CustomBinaryMarshaler 1310 | var val = &CustomBinaryMarshaler{Field: "DATA"} 1311 | var bit = []byte{cFixBin + 0x04, 68, 65, 84, 65} 1312 | var oth = []byte("DATA") 1313 | var enc = Encode(val) 1314 | var dec = Decode(bit) 1315 | DecodeInto(bit, &tmp) 1316 | So(enc, ShouldResemble, bit) 1317 | So(&tmp, ShouldResemble, val) 1318 | So(dec, ShouldResemble, oth) 1319 | }) 1320 | 1321 | Convey("CustomTextFailer will not encode and decode", t, func() { 1322 | var tmp CustomTextFailer 1323 | var val = &CustomTextFailer{Field: "TEXT"} 1324 | var bit = []byte{cFixBin + 0x04, 84, 69, 88, 84} 1325 | eer := NewEncoder(bytes.NewBuffer(nil)).Encode(val) 1326 | der := NewDecoder(bytes.NewReader(bit)).Decode(&tmp) 1327 | So(eer, ShouldNotBeNil) 1328 | So(der, ShouldNotBeNil) 1329 | }) 1330 | 1331 | Convey("CustomBinaryFailer will not encode and decode", t, func() { 1332 | var tmp CustomBinaryFailer 1333 | var val = &CustomBinaryFailer{Field: "DATA"} 1334 | var bit = []byte{cFixBin + 0x04, 68, 65, 84, 65} 1335 | eer := NewEncoder(bytes.NewBuffer(nil)).Encode(val) 1336 | der := NewDecoder(bytes.NewReader(bit)).Decode(&tmp) 1337 | So(eer, ShouldNotBeNil) 1338 | So(der, ShouldNotBeNil) 1339 | }) 1340 | 1341 | Convey("func will not encode and decode", t, func() { 1342 | var tmp interface{} 1343 | var val = func() {} 1344 | var bit = []byte{cNil} 1345 | var oth = interface{}(nil) 1346 | var enc = Encode(val) 1347 | var dec = Decode(bit) 1348 | So(enc, ShouldResemble, bit) 1349 | So(tmp, ShouldResemble, oth) 1350 | So(dec, ShouldResemble, oth) 1351 | }) 1352 | 1353 | Convey("channel will not encode and decode", t, func() { 1354 | var tmp interface{} 1355 | var val = make(chan int) 1356 | var bit = []byte{cNil} 1357 | var oth = interface{}(nil) 1358 | var enc = Encode(val) 1359 | var dec = Decode(bit) 1360 | So(enc, ShouldResemble, bit) 1361 | So(tmp, ShouldResemble, oth) 1362 | So(dec, ShouldResemble, oth) 1363 | }) 1364 | 1365 | } 1366 | 1367 | func isNotNum(v reflect.Kind) bool { 1368 | switch v { 1369 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 1370 | return false 1371 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 1372 | return false 1373 | } 1374 | return true 1375 | } 1376 | 1377 | func isNotMap(v reflect.Kind) bool { 1378 | return v != reflect.Map && v != reflect.Struct 1379 | } 1380 | 1381 | func isNotFloat(v reflect.Kind) bool { 1382 | return v != reflect.Float32 && v != reflect.Float64 1383 | } 1384 | 1385 | func isNotComplex(v reflect.Kind) bool { 1386 | return v != reflect.Complex64 && v != reflect.Complex128 1387 | } 1388 | 1389 | func tester(out, val interface{}) { 1390 | buf := bytes.NewBuffer(nil) 1391 | enc := NewEncoder(buf) 1392 | eer := enc.Encode(val) 1393 | dec := NewDecoder(buf) 1394 | der := dec.Decode(out) 1395 | So(eer, ShouldBeNil) 1396 | So(der, ShouldNotBeNil) 1397 | } 1398 | 1399 | func TestInvariants(t *testing.T) { 1400 | 1401 | tme, _ := time.Parse(time.RFC3339, "1987-06-22T08:00:00.123456789Z") 1402 | 1403 | obj := []interface{}{ 1404 | true, 1405 | false, 1406 | str, 1407 | bin, 1408 | lng, 1409 | tme, 1410 | CustomInt(1), 1411 | CustomString("Hi"), 1412 | float32(math.Pi), 1413 | float64(math.Pi), 1414 | complex64(math.Pi), 1415 | complex128(math.Pi), 1416 | []bool{true, false}, 1417 | []string{"one", "two"}, 1418 | []int{1, 2, 3, math.MaxInt8}, 1419 | []int8{1, 2, 3, math.MaxInt8}, 1420 | []int16{1, 2, 3, math.MaxInt16}, 1421 | []int32{1, 2, 3, math.MaxInt32}, 1422 | []int64{1, 2, 3, math.MaxInt64}, 1423 | []uint{1, 2, 3, math.MaxUint16}, 1424 | []uint16{1, 2, 3, math.MaxUint16}, 1425 | []uint32{1, 2, 3, math.MaxUint32}, 1426 | []uint64{1, 2, 3, math.MaxUint64}, 1427 | []float32{1, 2, 3, math.Pi}, 1428 | []float64{1, 2, 3, math.Pi}, 1429 | []complex64{1, 2, 3, math.MaxUint64}, 1430 | []complex128{1, 2, 3, math.MaxUint64}, 1431 | []time.Time{tme, tme, tme, tme, tme, tme}, 1432 | []interface{}{int8(1), "2", int16(3), int32(4), uint64(5)}, 1433 | Tested{"test", []byte("test"), []string{"1", "2"}, map[string]string{"1": "2"}, false, 25, "", ""}, 1434 | Corked{"test", []byte("test"), []string{"1", "2"}, map[string]string{"1": "2"}, false, 25, "", ""}, 1435 | Selfed{"test", []byte("test"), []string{"1", "2"}, map[string]string{"1": "2"}, false, 25, "", ""}, 1436 | map[string]int{}, 1437 | map[string]uint{}, 1438 | map[string]bool{}, 1439 | map[string]string{}, 1440 | map[int]interface{}{}, 1441 | map[uint]interface{}{}, 1442 | map[bool]interface{}{}, 1443 | map[string]interface{}{}, 1444 | map[time.Time]interface{}{}, 1445 | map[string]interface{}{ 1446 | "1": "test", 1447 | "2": map[interface{}]interface{}{ 1448 | true: []byte("Check"), 1449 | }, 1450 | "3": map[interface{}]interface{}{ 1451 | "str": str, 1452 | "bin": bin, 1453 | "lng": lng, 1454 | }, 1455 | }, 1456 | } 1457 | 1458 | for _, v := range obj { 1459 | 1460 | Convey(fmt.Sprintf("Attempt to incorrectly decode %T into incorrect types...", v), t, func() { 1461 | 1462 | if reflect.TypeOf(v).Kind() != reflect.Bool { 1463 | var out bool 1464 | tester(&out, v) 1465 | } 1466 | 1467 | if reflect.TypeOf(v).Kind() != reflect.String { 1468 | var out string 1469 | tester(&out, v) 1470 | } 1471 | 1472 | if isNotNum(reflect.TypeOf(v).Kind()) { 1473 | var out int 1474 | tester(&out, v) 1475 | } 1476 | 1477 | if isNotNum(reflect.TypeOf(v).Kind()) { 1478 | var out int8 1479 | tester(&out, v) 1480 | } 1481 | 1482 | if isNotNum(reflect.TypeOf(v).Kind()) { 1483 | var out int16 1484 | tester(&out, v) 1485 | } 1486 | 1487 | if isNotNum(reflect.TypeOf(v).Kind()) { 1488 | var out int32 1489 | tester(&out, v) 1490 | } 1491 | 1492 | if isNotNum(reflect.TypeOf(v).Kind()) { 1493 | var out int64 1494 | tester(&out, v) 1495 | } 1496 | 1497 | if isNotNum(reflect.TypeOf(v).Kind()) { 1498 | var out uint 1499 | tester(&out, v) 1500 | } 1501 | 1502 | if isNotNum(reflect.TypeOf(v).Kind()) { 1503 | var out uint16 1504 | tester(&out, v) 1505 | } 1506 | 1507 | if isNotNum(reflect.TypeOf(v).Kind()) { 1508 | var out uint32 1509 | tester(&out, v) 1510 | } 1511 | 1512 | if isNotNum(reflect.TypeOf(v).Kind()) { 1513 | var out uint64 1514 | tester(&out, v) 1515 | } 1516 | 1517 | if isNotFloat(reflect.TypeOf(v).Kind()) { 1518 | var out float32 1519 | tester(&out, v) 1520 | } 1521 | 1522 | if isNotFloat(reflect.TypeOf(v).Kind()) { 1523 | var out float64 1524 | tester(&out, v) 1525 | } 1526 | 1527 | if isNotComplex(reflect.TypeOf(v).Kind()) { 1528 | var out complex64 1529 | tester(&out, v) 1530 | } 1531 | 1532 | if isNotComplex(reflect.TypeOf(v).Kind()) { 1533 | var out complex128 1534 | tester(&out, v) 1535 | } 1536 | 1537 | if reflect.TypeOf(v) != reflect.TypeOf(time.Time{}) { 1538 | var out time.Time 1539 | tester(&out, v) 1540 | } 1541 | 1542 | // -------------------------------------------------- 1543 | 1544 | if reflect.TypeOf(v).Kind() != reflect.Slice { 1545 | var out []bool 1546 | tester(&out, v) 1547 | } 1548 | 1549 | if reflect.TypeOf(v).Kind() != reflect.Slice { 1550 | var out []string 1551 | tester(&out, v) 1552 | } 1553 | 1554 | if reflect.TypeOf(v).Kind() != reflect.Slice { 1555 | var out []int 1556 | tester(&out, v) 1557 | } 1558 | 1559 | if reflect.TypeOf(v).Kind() != reflect.Slice { 1560 | var out []int8 1561 | tester(&out, v) 1562 | } 1563 | 1564 | if reflect.TypeOf(v).Kind() != reflect.Slice { 1565 | var out []int16 1566 | tester(&out, v) 1567 | } 1568 | 1569 | if reflect.TypeOf(v).Kind() != reflect.Slice { 1570 | var out []int32 1571 | tester(&out, v) 1572 | } 1573 | 1574 | if reflect.TypeOf(v).Kind() != reflect.Slice { 1575 | var out []int64 1576 | tester(&out, v) 1577 | } 1578 | 1579 | if reflect.TypeOf(v).Kind() != reflect.Slice { 1580 | var out []uint 1581 | tester(&out, v) 1582 | } 1583 | 1584 | if reflect.TypeOf(v).Kind() != reflect.Slice { 1585 | var out []uint8 1586 | tester(&out, v) 1587 | } 1588 | 1589 | if reflect.TypeOf(v).Kind() != reflect.Slice { 1590 | var out []uint16 1591 | tester(&out, v) 1592 | } 1593 | 1594 | if reflect.TypeOf(v).Kind() != reflect.Slice { 1595 | var out []uint32 1596 | tester(&out, v) 1597 | } 1598 | 1599 | if reflect.TypeOf(v).Kind() != reflect.Slice { 1600 | var out []uint64 1601 | tester(&out, v) 1602 | } 1603 | 1604 | if reflect.TypeOf(v).Kind() != reflect.Slice { 1605 | var out []float32 1606 | tester(&out, v) 1607 | } 1608 | 1609 | if reflect.TypeOf(v).Kind() != reflect.Slice { 1610 | var out []float64 1611 | tester(&out, v) 1612 | } 1613 | 1614 | if reflect.TypeOf(v).Kind() != reflect.Slice { 1615 | var out []complex64 1616 | tester(&out, v) 1617 | } 1618 | 1619 | if reflect.TypeOf(v).Kind() != reflect.Slice { 1620 | var out []complex128 1621 | tester(&out, v) 1622 | } 1623 | 1624 | if reflect.TypeOf(v).Kind() != reflect.Slice { 1625 | var out []time.Time 1626 | tester(&out, v) 1627 | } 1628 | 1629 | if reflect.TypeOf(v).Kind() != reflect.Slice { 1630 | var out []interface{} 1631 | tester(&out, v) 1632 | } 1633 | 1634 | // -------------------------------------------------- 1635 | 1636 | if isNotMap(reflect.TypeOf(v).Kind()) { 1637 | var out map[string]int 1638 | tester(&out, v) 1639 | } 1640 | 1641 | if isNotMap(reflect.TypeOf(v).Kind()) { 1642 | var out map[string]uint 1643 | tester(&out, v) 1644 | } 1645 | 1646 | if isNotMap(reflect.TypeOf(v).Kind()) { 1647 | var out map[string]bool 1648 | tester(&out, v) 1649 | } 1650 | 1651 | if isNotMap(reflect.TypeOf(v).Kind()) { 1652 | var out map[string]string 1653 | tester(&out, v) 1654 | } 1655 | 1656 | if isNotMap(reflect.TypeOf(v).Kind()) { 1657 | var out map[string]interface{} 1658 | tester(&out, v) 1659 | } 1660 | 1661 | if isNotMap(reflect.TypeOf(v).Kind()) { 1662 | var out map[interface{}]interface{} 1663 | tester(&out, v) 1664 | } 1665 | 1666 | }) 1667 | 1668 | } 1669 | 1670 | } 1671 | 1672 | func sxpand(arg string, num int) (out string) { 1673 | for i := 0; i < num; i++ { 1674 | out = out + arg 1675 | } 1676 | return 1677 | } 1678 | func bxpand(arg []byte, num int) (out []byte) { 1679 | for i := 0; i < num; i++ { 1680 | out = append(out, arg...) 1681 | } 1682 | return 1683 | } 1684 | 1685 | func extend(args ...interface{}) (out []byte) { 1686 | for _, a := range args { 1687 | switch v := a.(type) { 1688 | case int: 1689 | out = append(out, byte(v)) 1690 | case byte: 1691 | out = append(out, v) 1692 | case []byte: 1693 | out = append(out, v...) 1694 | } 1695 | } 1696 | return 1697 | } 1698 | 1699 | func TestLargeEncoderDecoder(t *testing.T) { 1700 | 1701 | var obj = []interface{}{ 1702 | sxpand(str, 5), 1703 | sxpand(str, 10), 1704 | sxpand(str, 50), 1705 | sxpand(str, 100), 1706 | sxpand(str, 1000), 1707 | sxpand(str, 5000), 1708 | bxpand(bin, 5), 1709 | bxpand(bin, 10), 1710 | bxpand(bin, 50), 1711 | bxpand(bin, 100), 1712 | bxpand(bin, 1000), 1713 | bxpand(bin, 5000), 1714 | } 1715 | 1716 | var src = extend( 1717 | cFixArr+0x0C, 1718 | cStr16, 1, 34, bxpand(bin, 5), 1719 | cStr16, 2, 68, bxpand(bin, 10), 1720 | cStr16, 11, 84, bxpand(bin, 50), 1721 | cStr16, 22, 168, bxpand(bin, 100), 1722 | cStr16, 226, 144, bxpand(bin, 1000), 1723 | cStr32, 0, 4, 108, 208, bxpand(bin, 5000), 1724 | cBin16, 1, 34, bxpand(bin, 5), 1725 | cBin16, 2, 68, bxpand(bin, 10), 1726 | cBin16, 11, 84, bxpand(bin, 50), 1727 | cBin16, 22, 168, bxpand(bin, 100), 1728 | cBin16, 226, 144, bxpand(bin, 1000), 1729 | cBin32, 0, 4, 108, 208, bxpand(bin, 5000), 1730 | ) 1731 | 1732 | Convey("Large encoder data encodes correctly", t, func() { 1733 | var dst []byte 1734 | enc := NewEncoderBytesFromPool(&dst) 1735 | enc.Encode(obj) 1736 | enc.Reset() 1737 | So(dst, ShouldResemble, src) 1738 | }) 1739 | 1740 | Convey("Large decoder data decodes correctly", t, func() { 1741 | var dst []interface{} 1742 | dec := NewDecoderBytesFromPool(src) 1743 | dec.Decode(&dst) 1744 | dec.Reset() 1745 | So(dst, ShouldResemble, obj) 1746 | }) 1747 | 1748 | } 1749 | -------------------------------------------------------------------------------- /decode.go: -------------------------------------------------------------------------------- 1 | // Copyright © SurrealDB Ltd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package cork 16 | 17 | import ( 18 | "io" 19 | "sync" 20 | ) 21 | 22 | // Decoder represents a CORK decoder. 23 | type Decoder struct { 24 | h *Handle 25 | r *Reader 26 | p bool 27 | } 28 | 29 | var decoders = sync.Pool{ 30 | New: func() interface{} { 31 | return &Decoder{ 32 | r: newReader(), 33 | h: new(Handle), 34 | p: true, 35 | } 36 | }, 37 | } 38 | 39 | // Decode decodes binary data. 40 | func Decode(src []byte) (dst interface{}) { 41 | dec := NewDecoderBytesFromPool(src) 42 | dec.Decode(&dst) 43 | dec.Reset() 44 | return 45 | } 46 | 47 | // DecodeInto decodes a byte slice into a Go object. 48 | func DecodeInto(src []byte, dst interface{}) { 49 | dec := NewDecoderBytesFromPool(src) 50 | dec.Decode(dst) 51 | dec.Reset() 52 | return 53 | } 54 | 55 | // NewDecoder returns a Decoder for decoding from an io.Reader. 56 | func NewDecoder(r io.Reader) *Decoder { 57 | d := &Decoder{r: newReader(), h: new(Handle)} 58 | d.r.r.Reset(r) 59 | return d 60 | } 61 | 62 | // NewDecoderBytes returns a Decoder for decoding directly from a byte slice. 63 | func NewDecoderBytes(b []byte) *Decoder { 64 | d := &Decoder{r: newReader(), h: new(Handle)} 65 | d.r.r.ResetBytes(b) 66 | return d 67 | } 68 | 69 | // NewDecoderFromPool returns a Decoder for decoding into an 70 | // io.Reader. The Decoder is taken from a pool of decoders, and 71 | // must be put back when finished, using d.Reset(). 72 | func NewDecoderFromPool(r io.Reader) *Decoder { 73 | d := decoders.Get().(*Decoder) 74 | d.r.r.Reset(r) 75 | return d 76 | } 77 | 78 | // NewDecoderBytesFromPool returns a Decoder for decoding directly 79 | // from a byte slice. The Decoder is taken from a pool of decoders, 80 | // and must be put back when finished, using d.Reset(). 81 | func NewDecoderBytesFromPool(b []byte) *Decoder { 82 | d := decoders.Get().(*Decoder) 83 | d.r.r.ResetBytes(b) 84 | return d 85 | } 86 | 87 | // Reset flushes adds the Decoder back into the sync pool. If the 88 | // Decoder was not originally from the sync pool, then the 89 | // Decoder is discarded. 90 | func (d *Decoder) Reset() { 91 | if d.p { 92 | decoders.Put(d) 93 | } 94 | } 95 | 96 | // Options sets the configuration options that the Decoder should use. 97 | func (d *Decoder) Options(h *Handle) *Decoder { 98 | d.r.h, d.h = h, h 99 | return d 100 | } 101 | 102 | /* 103 | Decode decodes the stream into the 'dst' object. 104 | 105 | The decoder can not decode into a nil pointer, but can decode into a nil interface. 106 | If you do not know what type of stream it is, pass in a pointer to a nil interface. 107 | We will decode and store a value in that nil interface. 108 | 109 | When decoding into a nil interface{}, we will decode into an appropriate value based 110 | on the contents of the stream. When decoding into a non-nil interface{} value, the 111 | mode of encoding is based on the type of the value. 112 | 113 | Example: 114 | 115 | // Decoding into a non-nil typed value 116 | var s string 117 | buf := bytes.NewBuffer(src) 118 | err = cork.NewDecoder(buf).Decode(&s) 119 | 120 | // Decoding into nil interface 121 | var v interface{} 122 | buf := bytes.NewBuffer(src) 123 | err := cork.NewDecoder(buf).Decode(&v) 124 | 125 | */ 126 | func (d *Decoder) Decode(dst interface{}) (err error) { 127 | defer func() { 128 | if r := recover(); r != nil { 129 | if catch, ok := r.(error); ok { 130 | err = catch 131 | } 132 | } 133 | }() 134 | d.r.DecodeAny(dst) 135 | return 136 | } 137 | -------------------------------------------------------------------------------- /decode_test.go: -------------------------------------------------------------------------------- 1 | // Copyright © SurrealDB Ltd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package cork 16 | 17 | import ( 18 | "bytes" 19 | "testing" 20 | 21 | . "github.com/smartystreets/goconvey/convey" 22 | ) 23 | 24 | func TestDecode(t *testing.T) { 25 | 26 | var src = "Hello" 27 | 28 | var val = interface{}("Hello") 29 | 30 | var dst = []byte{cFixStr + 0x05, 72, 101, 108, 108, 111} 31 | 32 | Convey("Can use Decode", t, func() { 33 | out := Decode(dst) 34 | So(out, ShouldResemble, val) 35 | }) 36 | 37 | Convey("Can use DecodeInto", t, func() { 38 | var out string 39 | DecodeInto(dst, &out) 40 | So(out, ShouldResemble, src) 41 | }) 42 | 43 | Convey("Can use NewDecoder", t, func() { 44 | var out string 45 | var buf = bytes.NewReader(dst) 46 | NewDecoder(buf).Decode(&out) 47 | So(out, ShouldResemble, src) 48 | }) 49 | 50 | Convey("Can use NewDecoderBytes", t, func() { 51 | var out string 52 | NewDecoderBytes(dst).Decode(&out) 53 | So(out, ShouldResemble, src) 54 | }) 55 | 56 | Convey("Can use NewDecoderFromPool", t, func() { 57 | var out string 58 | var buf = bytes.NewReader(dst) 59 | NewDecoderFromPool(buf).Decode(&out) 60 | So(out, ShouldResemble, src) 61 | }) 62 | 63 | Convey("Can use NewDecoderBytesFromPool", t, func() { 64 | var out string 65 | NewDecoderBytesFromPool(dst).Decode(&out) 66 | So(out, ShouldResemble, src) 67 | }) 68 | 69 | } 70 | -------------------------------------------------------------------------------- /doc.go: -------------------------------------------------------------------------------- 1 | // Copyright © SurrealDB Ltd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /* 16 | 17 | CORK is a dynamic and static binary object serialization specification 18 | similar to GOB and MessagePack. CORK manages encoding and decoding binary 19 | data streams, for use in transmission of, or storage of data. 20 | 21 | Basics 22 | 23 | A CORK data stream is self-describing. Each data item in the stream is preceded 24 | by a description of its type, expressed in terms of a small set of predefined 25 | types. Pointers to values are not transmitted, but the contents are flattened 26 | and transmitted. 27 | 28 | To use cork, create an Encoder and present it with a series of data items as 29 | values or addresses that can be dereferenced to values. The Encoder makes sure 30 | all type information is sent before it is needed. At the receive side, a 31 | Decoder retrieves values from the encoded stream and unpacks them into local 32 | variables. 33 | 34 | Types 35 | 36 | CORK has built in support for the built-in Golang types 37 | 38 | nil 39 | bool 40 | string 41 | []byte 42 | int 43 | int8 44 | int16 45 | int32 46 | int64 47 | uint 48 | uint8 49 | uint16 50 | uint32 51 | uint64 52 | float32 53 | float64 54 | complex64 55 | complex128 56 | time.Time 57 | interface{} 58 | [] 59 | map[] 60 | 61 | Structs 62 | 63 | When a struct is encountered whilst encoding (and that struct does not satisfy 64 | the Corker interface) then the struct will be encoded into the stream as a map 65 | with the keys encoded as strings, and the values as the relevant type. Any 66 | struct tags describing how the struct should be encoded will be used. 67 | 68 | Corkers 69 | 70 | CORK allows applications to define application-specific types to be added 71 | to the encoding format. Each extended type must be assigned a unique byte 72 | from 0x00 upto 0xFF. Application-specific types (otherwise known as Corkers) 73 | are able to encode themselves into a binary data value, and are able to 74 | decode themselves from that same binary data value. 75 | 76 | To define a custom type, an application must ensure that the type satisfies 77 | the Corker interface, and must then register the type using the Register 78 | method. 79 | 80 | If a custom type is found in the stream when decoding, but no type with the 81 | specified unique byte is registered, then the binary data value will be 82 | decoded as a raw binary data value. 83 | 84 | Types and Values 85 | 86 | The source and destination values/types need not correspond exactly. For structs, 87 | fields (identified by name) that are in the source but absent from the receiving 88 | variable will be ignored. Fields that are in the receiving variable but missing 89 | from the transmitted type or value will be ignored in the destination. If a field 90 | with the same name is present in both, their types must be compatible. Both the 91 | receiver and transmitter will do all necessary indirection and dereferencing to 92 | convert between cork encoded data and actual Go values. For instance, a cork type 93 | that is schematically, 94 | 95 | struct { A, B int } 96 | 97 | can be sent from or received into any of these Go types: 98 | 99 | struct { A, B int } // the same 100 | *struct { A, B int } // extra indirection of the struct 101 | struct { *A, **B int } // extra indirection of the fields 102 | struct { A, B int64 } // different concrete value type; see below 103 | 104 | It may also be received into any of these: 105 | 106 | struct { A, B int } // the same 107 | struct { B, A int } // ordering doesn't matter; matching is by name 108 | struct { A, B, C int } // extra field (C) ignored 109 | struct { B int } // missing field (A) ignored; data will be dropped 110 | struct { B, C int } // missing field (A) ignored; extra field (C) ignored. 111 | 112 | Attempting to receive into these types will draw a decode error: 113 | 114 | struct { A int; B uint } // change of signedness for B 115 | struct { A int; B float } // change of type for B 116 | struct { } // no field names in common 117 | struct { C, D int } // no field names in common 118 | 119 | Integers can be serialized using two different methods: arbritrary precision or 120 | full precision. When using arbritrary precision, integers (int, int8, int16, int32, 121 | int64) and unsinged integers (uint, uint8, uint16, uint32, uint64) are encoded 122 | with a variable-length encoding using as few bytes as possible, and are decoded 123 | into the destination variable, or an integer with the necessary capacity (when 124 | decoding into a nil interface). When using full precision, all integers (int8, 125 | int16, int32, int64) and unsinged integers (uint8, uint16, uint32, uint64) are 126 | encoded with a fixed-length encoding format, and are able to be decoded into the 127 | corresponding variable type when decoding into a nil interface. 128 | 129 | Signed integers may be received into any signed integer variable: int, int16, etc.; 130 | unsigned integers may be received into any unsigned integer variable; and floating 131 | point values may be received into any floating point variable. However, 132 | the destination variable must be able to represent the value or the decode 133 | operation will fail. 134 | 135 | Structs, arrays and slices are also supported. Structs encode and decode only 136 | exported fields. Struct tags (using the 'cork' descriptor) can specify custom key 137 | names to be used when serailizing, and can be omitted entirely, or when empty using 138 | the 'omitempty' tag keyword. Strings and arrays of bytes are supported with a special, 139 | efficient representation. When a slice is decoded, if the existing slice has 140 | capacity the slice will be extended in place; if not, a new array is allocated. 141 | Regardless, the length of the resulting slice reports the number of elements decoded. 142 | 143 | In general, if allocation is required, the decoder will allocate memory. If not, 144 | it will update the destination variables with values read from the stream. It does 145 | not initialize them first, so if the destination is a compound value such as a 146 | map, struct, or slice, the decoded values will be merged elementwise into the 147 | existing variables. 148 | 149 | Functions and channels will not be encoded into a CORK. Attempting to encode 150 | such a value at the top level will fail. A struct field of chan or func type 151 | is treated exactly like an unexported field and is ignored. 152 | 153 | Specification 154 | 155 | The full specification can be found at http://github.com/surrealdb/cork/SPEC.md 156 | 157 | */ 158 | package cork 159 | -------------------------------------------------------------------------------- /encode.go: -------------------------------------------------------------------------------- 1 | // Copyright © SurrealDB Ltd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package cork 16 | 17 | import ( 18 | "io" 19 | "sync" 20 | ) 21 | 22 | // Encoder represents a CORK encoder. 23 | type Encoder struct { 24 | h *Handle 25 | w *Writer 26 | p bool 27 | } 28 | 29 | var encoders = sync.Pool{ 30 | New: func() interface{} { 31 | return &Encoder{ 32 | w: newWriter(), 33 | h: new(Handle), 34 | p: true, 35 | } 36 | }, 37 | } 38 | 39 | // Encode encodes a Go object. 40 | func Encode(src interface{}) (dst []byte) { 41 | enc := NewEncoderBytesFromPool(&dst) 42 | enc.Encode(src) 43 | enc.Reset() 44 | return 45 | } 46 | 47 | // EncodeInto encodes a Go object into a byte slice. 48 | func EncodeInto(src interface{}, dst *[]byte) { 49 | enc := NewEncoderBytesFromPool(dst) 50 | enc.Encode(src) 51 | enc.Reset() 52 | return 53 | } 54 | 55 | // NewEncoder returns an Encoder for encoding into an io.Writer. 56 | func NewEncoder(w io.Writer) *Encoder { 57 | e := &Encoder{w: newWriter(), h: new(Handle)} 58 | e.w.w.Reset(w) 59 | return e 60 | } 61 | 62 | // NewEncoderBytes returns an Encoder for encoding directly into a byte slice. 63 | func NewEncoderBytes(b *[]byte) *Encoder { 64 | e := &Encoder{w: newWriter(), h: new(Handle)} 65 | e.w.w.ResetBytes(b) 66 | return e 67 | } 68 | 69 | // NewEncoderFromPool returns an Encoder for encoding into an 70 | // io.Writer. The Encoder is taken from a pool of encoders, and 71 | // must be put back when finished, using e.Reset(). 72 | func NewEncoderFromPool(w io.Writer) *Encoder { 73 | e := encoders.Get().(*Encoder) 74 | e.w.w.Reset(w) 75 | return e 76 | } 77 | 78 | // NewEncoderBytesFromPool returns an Encoder for encoding directly 79 | // into a byte slice. The Encoder is taken from a pool of encoders, 80 | // and must be put back when finished, using e.Reset(). 81 | func NewEncoderBytesFromPool(b *[]byte) *Encoder { 82 | e := encoders.Get().(*Encoder) 83 | e.w.w.ResetBytes(b) 84 | return e 85 | } 86 | 87 | // Reset flushes any remaing data and adds the Encoder back into 88 | // the sync pool. If the Encoder was not originally from the 89 | // sync pool, then the Encoder is discarded. 90 | func (e *Encoder) Reset() { 91 | if e.p { 92 | encoders.Put(e) 93 | } 94 | } 95 | 96 | // Options sets the configuration options that the Encoder should use. 97 | func (e *Encoder) Options(h *Handle) *Encoder { 98 | e.w.h, e.h = h, h 99 | return e 100 | } 101 | 102 | /* 103 | Encode encodes the 'src' object into the stream. 104 | 105 | The decoder can be configured using struct tags. The 'cork' key if found will be 106 | analysed for any configuration options when encoding. 107 | 108 | Each exported struct field is encoded unless: 109 | - the field's tag is "-" 110 | - the field is empty and its tag specifies the "omitempty" option. 111 | 112 | When encoding a struct as a map, the first string in the tag (before the comma) 113 | will be used for the map key, and if not specified will default to the struct key 114 | name. 115 | 116 | The empty values (for omitempty option) are false, 0, any nil pointer or 117 | interface value, and any array, slice, map, or string of length zero. 118 | 119 | type Tester struct { 120 | Test bool `cork:"-"` // Skip this field 121 | Name string `cork:"name"` // Use key "name" in encode stream 122 | Size int32 `cork:"size"` // Use key "size" in encode stream 123 | Data []byte `cork:"data,omitempty"` // Use key data in encode stream, and omit if empty 124 | } 125 | 126 | Example: 127 | 128 | // Encoding a typed value 129 | var s string = "Hello" 130 | buf := bytes.NewBuffer(nil) 131 | err = cork.NewEncoder(buf).Encode(s) 132 | 133 | // Encoding a struct 134 | var t &Tester{Name: "Temp", Size: 0} 135 | buf := bytes.NewBuffer(nil) 136 | err = cork.NewEncoder(buf).Encode(t) 137 | 138 | */ 139 | func (e *Encoder) Encode(src interface{}) (err error) { 140 | defer func() { 141 | if r := recover(); r != nil { 142 | if catch, ok := r.(error); ok { 143 | err = catch 144 | } 145 | } 146 | }() 147 | e.w.EncodeAny(src) 148 | e.w.w.Flush() 149 | return 150 | } 151 | -------------------------------------------------------------------------------- /encode_test.go: -------------------------------------------------------------------------------- 1 | // Copyright © SurrealDB Ltd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package cork 16 | 17 | import ( 18 | "bytes" 19 | "testing" 20 | 21 | . "github.com/smartystreets/goconvey/convey" 22 | ) 23 | 24 | func TestEncode(t *testing.T) { 25 | 26 | var src = "Hello" 27 | 28 | var dst = []byte{cFixStr + 0x05, 72, 101, 108, 108, 111} 29 | 30 | Convey("Can use Encode", t, func() { 31 | out := Encode(src) 32 | So(out, ShouldResemble, dst) 33 | }) 34 | 35 | Convey("Can use EncodeInto", t, func() { 36 | var buf []byte 37 | EncodeInto(src, &buf) 38 | So(buf, ShouldResemble, dst) 39 | }) 40 | 41 | Convey("Can use NewEncoder", t, func() { 42 | var buf = bytes.NewBuffer(nil) 43 | NewEncoder(buf).Encode(src) 44 | So(buf.Bytes(), ShouldResemble, dst) 45 | }) 46 | 47 | Convey("Can use NewEncoderBytes", t, func() { 48 | var buf []byte 49 | NewEncoderBytes(&buf).Encode(src) 50 | So(buf, ShouldResemble, dst) 51 | }) 52 | 53 | Convey("Can use NewEncoderFromPool", t, func() { 54 | var buf = bytes.NewBuffer(nil) 55 | NewEncoderFromPool(buf).Encode(src) 56 | So(buf.Bytes(), ShouldResemble, dst) 57 | }) 58 | 59 | Convey("Can use NewEncoderBytesFromPool", t, func() { 60 | var buf []byte 61 | NewEncoderBytesFromPool(&buf).Encode(src) 62 | So(buf, ShouldResemble, dst) 63 | }) 64 | 65 | } 66 | -------------------------------------------------------------------------------- /errors.go: -------------------------------------------------------------------------------- 1 | // Copyright © SurrealDB Ltd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package cork 16 | 17 | import "errors" 18 | 19 | var fail = errors.New("Can't decode into type") 20 | -------------------------------------------------------------------------------- /fields.go: -------------------------------------------------------------------------------- 1 | // Copyright © SurrealDB Ltd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package cork 16 | 17 | import ( 18 | "reflect" 19 | "strings" 20 | ) 21 | 22 | type field struct { 23 | omit bool 24 | indx []int 25 | name string 26 | show string 27 | } 28 | 29 | func (f *field) Name() string { 30 | if len(f.show) > 0 { 31 | return f.show 32 | } 33 | return f.name 34 | } 35 | 36 | func newField(kind reflect.StructField) *field { 37 | 38 | // Field is private 39 | if len(kind.PkgPath) > 0 { 40 | return nil 41 | } 42 | 43 | // Field not supported 44 | switch kind.Type.Kind() { 45 | case reflect.Chan: 46 | return nil 47 | case reflect.Func: 48 | return nil 49 | } 50 | 51 | // Retrieve the tag 52 | tag := kind.Tag.Get(tag) 53 | 54 | // No tag specified 55 | if len(tag) == 0 { 56 | return &field{ 57 | omit: false, 58 | name: kind.Name, 59 | indx: kind.Index, 60 | } 61 | } 62 | 63 | // Field is ignored 64 | if tag == "-" { 65 | return nil 66 | } 67 | 68 | idx := strings.Index(tag, ",") 69 | 70 | // Field is renamed 71 | if idx < 0 { 72 | return &field{ 73 | omit: false, 74 | name: kind.Name, 75 | show: tag, 76 | indx: kind.Index, 77 | } 78 | } 79 | 80 | // Field is renamed 81 | if idx > 0 { 82 | return &field{ 83 | omit: tag[idx+1:] == "omitempty", 84 | name: kind.Name, 85 | show: tag[:idx], 86 | indx: kind.Index, 87 | } 88 | } 89 | 90 | // Immediate comma 91 | if idx == 0 { 92 | return &field{ 93 | omit: tag[idx+1:] == "omitempty", 94 | name: kind.Name, 95 | indx: kind.Index, 96 | } 97 | } 98 | 99 | return nil 100 | 101 | } 102 | 103 | func isEmpty(item reflect.Value) bool { 104 | switch item.Kind() { 105 | case reflect.Array, reflect.Map, reflect.Slice, reflect.String: 106 | return item.Len() == 0 107 | case reflect.Bool: 108 | return !item.Bool() 109 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 110 | return item.Int() == 0 111 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 112 | return item.Uint() == 0 113 | case reflect.Float32, reflect.Float64: 114 | return item.Float() == 0 115 | case reflect.Interface, reflect.Ptr: 116 | return item.IsNil() 117 | } 118 | return false 119 | } 120 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/surrealdb/cork 2 | 3 | go 1.17 4 | 5 | require ( 6 | github.com/smartystreets/goconvey v1.7.2 7 | github.com/surrealdb/bump v0.0.0-20211208102305-88d509230106 8 | ) 9 | 10 | require ( 11 | github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 // indirect 12 | github.com/jtolds/gls v4.20.0+incompatible // indirect 13 | github.com/smartystreets/assertions v1.2.0 // indirect 14 | ) 15 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= 2 | github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= 3 | github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= 4 | github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= 5 | github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs= 6 | github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= 7 | github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg= 8 | github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3Pg9vgXWeJpQFMM= 9 | github.com/surrealdb/bump v0.0.0-20211208102305-88d509230106 h1:y8XTv9GabZwtbGVa4I1AIyucLjmqrTGocyuKh9MUCrU= 10 | github.com/surrealdb/bump v0.0.0-20211208102305-88d509230106/go.mod h1:7j+Wcc4B4QM++XXvz8wCpFdSRWHvWLWMr7iC6495KoM= 11 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 12 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 13 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 14 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 15 | golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 16 | -------------------------------------------------------------------------------- /handle.go: -------------------------------------------------------------------------------- 1 | // Copyright © SurrealDB Ltd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package cork 16 | 17 | type Handle struct { 18 | // SortMaps specifies whether maps should be sorted before 19 | // being encoded into CORK. This guarantees that the same 20 | // input data is always encoded into the same binary data. 21 | SortMaps bool 22 | // ArrType specifies the type of slice to use when decoding 23 | // into a nil interface during schema-less decoding of a 24 | // slice in the stream. 25 | // 26 | // If not specified, we use []interface{} 27 | ArrType interface{} 28 | 29 | // MapType specifies the type of map to use when decoding 30 | // into a nil interface during schema-less decoding of a 31 | // map in the stream. 32 | // 33 | // If not specified, we use map[interface{}]interface{} 34 | MapType interface{} 35 | } 36 | -------------------------------------------------------------------------------- /handle_test.go: -------------------------------------------------------------------------------- 1 | // Copyright © SurrealDB Ltd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package cork 16 | 17 | import ( 18 | "math" 19 | "reflect" 20 | "testing" 21 | "time" 22 | 23 | . "github.com/smartystreets/goconvey/convey" 24 | ) 25 | 26 | func TestOptions(t *testing.T) { 27 | 28 | jim, _ := time.Parse(time.RFC3339, "1985-05-18T08:00:00.123456789Z") 29 | tme, _ := time.Parse(time.RFC3339, "1987-06-22T08:00:00.123456789Z") 30 | 31 | Convey("Can create []bool array type", t, func() { 32 | var tmp interface{} 33 | var buf []byte 34 | var val = []bool{true, false} 35 | var opt = &Handle{ArrType: make([]bool, 0)} 36 | NewEncoderBytes(&buf).Options(opt).Encode(val) 37 | NewDecoderBytes(buf).Options(opt).Decode(&tmp) 38 | So(tmp, ShouldResemble, val) 39 | }) 40 | 41 | Convey("Can create []int array type", t, func() { 42 | var tmp interface{} 43 | var buf []byte 44 | var val = []int{1, 2, 3} 45 | var opt = &Handle{ArrType: make([]int, 0)} 46 | NewEncoderBytes(&buf).Options(opt).Encode(val) 47 | NewDecoderBytes(buf).Options(opt).Decode(&tmp) 48 | So(tmp, ShouldResemble, val) 49 | }) 50 | 51 | Convey("Can create []int8 array type", t, func() { 52 | var tmp interface{} 53 | var buf []byte 54 | var val = []int8{1, 2, 3} 55 | var opt = &Handle{ArrType: make([]int8, 0)} 56 | NewEncoderBytes(&buf).Options(opt).Encode(val) 57 | NewDecoderBytes(buf).Options(opt).Decode(&tmp) 58 | So(tmp, ShouldResemble, val) 59 | }) 60 | 61 | Convey("Can create []int16 array type", t, func() { 62 | var tmp interface{} 63 | var buf []byte 64 | var val = []int16{1, 2, 3} 65 | var opt = &Handle{ArrType: make([]int16, 0)} 66 | NewEncoderBytes(&buf).Options(opt).Encode(val) 67 | NewDecoderBytes(buf).Options(opt).Decode(&tmp) 68 | So(tmp, ShouldResemble, val) 69 | }) 70 | 71 | Convey("Can create []int32 array type", t, func() { 72 | var tmp interface{} 73 | var buf []byte 74 | var val = []int32{1, 2, 3} 75 | var opt = &Handle{ArrType: make([]int32, 0)} 76 | NewEncoderBytes(&buf).Options(opt).Encode(val) 77 | NewDecoderBytes(buf).Options(opt).Decode(&tmp) 78 | So(tmp, ShouldResemble, val) 79 | }) 80 | 81 | Convey("Can create []int64 array type", t, func() { 82 | var tmp interface{} 83 | var buf []byte 84 | var val = []int64{1, 2, 3} 85 | var opt = &Handle{ArrType: make([]int64, 0)} 86 | NewEncoderBytes(&buf).Options(opt).Encode(val) 87 | NewDecoderBytes(buf).Options(opt).Decode(&tmp) 88 | So(tmp, ShouldResemble, val) 89 | }) 90 | 91 | Convey("Can create []uint array type", t, func() { 92 | var tmp interface{} 93 | var buf []byte 94 | var val = []uint{1, 2, 3} 95 | var opt = &Handle{ArrType: make([]uint, 0)} 96 | NewEncoderBytes(&buf).Options(opt).Encode(val) 97 | NewDecoderBytes(buf).Options(opt).Decode(&tmp) 98 | So(tmp, ShouldResemble, val) 99 | }) 100 | 101 | Convey("Can create []uint8 array type", t, func() { 102 | var tmp interface{} 103 | var buf []byte 104 | var val = []uint8{1, 2, 3} 105 | var opt = &Handle{ArrType: make([]uint8, 0)} 106 | NewEncoderBytes(&buf).Options(opt).Encode(val) 107 | NewDecoderBytes(buf).Options(opt).Decode(&tmp) 108 | So(tmp, ShouldResemble, val) 109 | }) 110 | 111 | Convey("Can create []uint16 array type", t, func() { 112 | var tmp interface{} 113 | var buf []byte 114 | var val = []uint16{1, 2, 3} 115 | var opt = &Handle{ArrType: make([]uint16, 0)} 116 | NewEncoderBytes(&buf).Options(opt).Encode(val) 117 | NewDecoderBytes(buf).Options(opt).Decode(&tmp) 118 | So(tmp, ShouldResemble, val) 119 | }) 120 | 121 | Convey("Can create []uint32 array type", t, func() { 122 | var tmp interface{} 123 | var buf []byte 124 | var val = []uint32{1, 2, 3} 125 | var opt = &Handle{ArrType: make([]uint32, 0)} 126 | NewEncoderBytes(&buf).Options(opt).Encode(val) 127 | NewDecoderBytes(buf).Options(opt).Decode(&tmp) 128 | So(tmp, ShouldResemble, val) 129 | }) 130 | 131 | Convey("Can create []uint64 array type", t, func() { 132 | var tmp interface{} 133 | var buf []byte 134 | var val = []uint64{1, 2, 3} 135 | var opt = &Handle{ArrType: make([]uint64, 0)} 136 | NewEncoderBytes(&buf).Options(opt).Encode(val) 137 | NewDecoderBytes(buf).Options(opt).Decode(&tmp) 138 | So(tmp, ShouldResemble, val) 139 | }) 140 | 141 | Convey("Can create []string array type", t, func() { 142 | var tmp interface{} 143 | var buf []byte 144 | var val = []string{"hello", "world"} 145 | var opt = &Handle{ArrType: make([]string, 0)} 146 | NewEncoderBytes(&buf).Options(opt).Encode(val) 147 | NewDecoderBytes(buf).Options(opt).Decode(&tmp) 148 | So(tmp, ShouldResemble, val) 149 | }) 150 | 151 | Convey("Can create []float32 array type", t, func() { 152 | var tmp interface{} 153 | var buf []byte 154 | var val = []float32{math.Pi, math.Pi} 155 | var opt = &Handle{ArrType: make([]float32, 0)} 156 | NewEncoderBytes(&buf).Options(opt).Encode(val) 157 | NewDecoderBytes(buf).Options(opt).Decode(&tmp) 158 | So(tmp, ShouldResemble, val) 159 | }) 160 | 161 | Convey("Can create []float64 array type", t, func() { 162 | var tmp interface{} 163 | var buf []byte 164 | var val = []float64{math.Pi, math.Pi} 165 | var opt = &Handle{ArrType: make([]float64, 0)} 166 | NewEncoderBytes(&buf).Options(opt).Encode(val) 167 | NewDecoderBytes(buf).Options(opt).Decode(&tmp) 168 | So(tmp, ShouldResemble, val) 169 | }) 170 | 171 | Convey("Can create []complex64 array type", t, func() { 172 | var tmp interface{} 173 | var buf []byte 174 | var val = []complex64{math.Pi, math.Pi} 175 | var opt = &Handle{ArrType: make([]complex64, 0)} 176 | NewEncoderBytes(&buf).Options(opt).Encode(val) 177 | NewDecoderBytes(buf).Options(opt).Decode(&tmp) 178 | So(tmp, ShouldResemble, val) 179 | }) 180 | 181 | Convey("Can create []complex128 array type", t, func() { 182 | var tmp interface{} 183 | var buf []byte 184 | var val = []complex128{math.Pi, math.Pi} 185 | var opt = &Handle{ArrType: make([]complex128, 0)} 186 | NewEncoderBytes(&buf).Options(opt).Encode(val) 187 | NewDecoderBytes(buf).Options(opt).Decode(&tmp) 188 | So(tmp, ShouldResemble, val) 189 | }) 190 | 191 | Convey("Can create []time.Time array type", t, func() { 192 | var tmp interface{} 193 | var buf []byte 194 | var val = []time.Time{tme, tme} 195 | var opt = &Handle{ArrType: make([]time.Time, 0)} 196 | NewEncoderBytes(&buf).Options(opt).Encode(val) 197 | NewDecoderBytes(buf).Options(opt).Decode(&tmp) 198 | So(tmp, ShouldResemble, val) 199 | }) 200 | 201 | Convey("Can create []interface{} array type", t, func() { 202 | var tmp interface{} 203 | var buf []byte 204 | var val = []interface{}{true, 1, 2, 3, "test", math.Pi, tme} 205 | var opt = &Handle{ArrType: make([]interface{}, 0)} 206 | NewEncoderBytes(&buf).Options(opt).Encode(val) 207 | NewDecoderBytes(buf).Options(opt).Decode(&tmp) 208 | So(tmp, ShouldResemble, val) 209 | }) 210 | 211 | Convey("Can create reflect array type", t, func() { 212 | var tmp interface{} 213 | var buf []byte 214 | var val = []Simple{} 215 | var opt = &Handle{ArrType: reflect.TypeOf(val)} 216 | NewEncoderBytes(&buf).Options(opt).Encode(val) 217 | NewDecoderBytes(buf).Options(opt).Decode(&tmp) 218 | So(tmp, ShouldResemble, val) 219 | }) 220 | 221 | Convey("Can create map[string]int map type", t, func() { 222 | var tmp interface{} 223 | var buf []byte 224 | var val = map[string]int{"test": 1} 225 | var opt = &Handle{SortMaps: true, MapType: make(map[string]int)} 226 | NewEncoderBytes(&buf).Options(opt).Encode(val) 227 | So(buf, ShouldResemble, []byte{209, 132, 116, 101, 115, 116, 1}) 228 | NewDecoderBytes(buf).Options(opt).Decode(&tmp) 229 | So(tmp, ShouldResemble, val) 230 | }) 231 | 232 | Convey("Can create map[string]uint map type", t, func() { 233 | var tmp interface{} 234 | var buf []byte 235 | var val = map[string]uint{"test": 1, "other": 5} 236 | var opt = &Handle{SortMaps: true, MapType: make(map[string]uint)} 237 | NewEncoderBytes(&buf).Options(opt).Encode(val) 238 | So(buf, ShouldResemble, []byte{210, 133, 111, 116, 104, 101, 114, 5, 132, 116, 101, 115, 116, 1}) 239 | NewDecoderBytes(buf).Options(opt).Decode(&tmp) 240 | So(tmp, ShouldResemble, val) 241 | }) 242 | 243 | Convey("Can create map[string]bool map type", t, func() { 244 | var tmp interface{} 245 | var buf []byte 246 | var val = map[string]bool{"test": true, "other": false} 247 | var opt = &Handle{SortMaps: true, MapType: make(map[string]bool)} 248 | NewEncoderBytes(&buf).Options(opt).Encode(val) 249 | So(buf, ShouldResemble, []byte{210, 133, 111, 116, 104, 101, 114, 226, 132, 116, 101, 115, 116, 225}) 250 | NewDecoderBytes(buf).Options(opt).Decode(&tmp) 251 | So(tmp, ShouldResemble, val) 252 | }) 253 | 254 | Convey("Can create map[string]string map type", t, func() { 255 | var tmp interface{} 256 | var buf []byte 257 | var val = map[string]string{"test": "some", "other": "none"} 258 | var opt = &Handle{SortMaps: true, MapType: make(map[string]string)} 259 | NewEncoderBytes(&buf).Options(opt).Encode(val) 260 | So(buf, ShouldResemble, []byte{210, 133, 111, 116, 104, 101, 114, 132, 110, 111, 110, 101, 132, 116, 101, 115, 116, 132, 115, 111, 109, 101}) 261 | NewDecoderBytes(buf).Options(opt).Decode(&tmp) 262 | So(tmp, ShouldResemble, val) 263 | }) 264 | 265 | Convey("Can create map[int]interface{} map type", t, func() { 266 | var tmp interface{} 267 | var buf []byte 268 | var val = map[int]interface{}{5: "test", 1: "other"} 269 | var opt = &Handle{SortMaps: true, MapType: make(map[int]interface{})} 270 | NewEncoderBytes(&buf).Options(opt).Encode(val) 271 | So(buf, ShouldResemble, []byte{210, 1, 133, 111, 116, 104, 101, 114, 5, 132, 116, 101, 115, 116}) 272 | NewDecoderBytes(buf).Options(opt).Decode(&tmp) 273 | So(tmp, ShouldResemble, val) 274 | }) 275 | 276 | Convey("Can create map[uint]interface{} map type", t, func() { 277 | var tmp interface{} 278 | var buf []byte 279 | var val = map[uint]interface{}{5: "test", 1: "other"} 280 | var opt = &Handle{SortMaps: true, MapType: make(map[uint]interface{})} 281 | NewEncoderBytes(&buf).Options(opt).Encode(val) 282 | So(buf, ShouldResemble, []byte{210, 1, 133, 111, 116, 104, 101, 114, 5, 132, 116, 101, 115, 116}) 283 | NewDecoderBytes(buf).Options(opt).Decode(&tmp) 284 | So(tmp, ShouldResemble, val) 285 | }) 286 | 287 | Convey("Can create map[string]interface{} map type", t, func() { 288 | var tmp interface{} 289 | var buf []byte 290 | var val = map[string]interface{}{"test": "test", "other": "other"} 291 | var opt = &Handle{SortMaps: true, MapType: make(map[string]interface{})} 292 | NewEncoderBytes(&buf).Options(opt).Encode(val) 293 | So(buf, ShouldResemble, []byte{210, 133, 111, 116, 104, 101, 114, 133, 111, 116, 104, 101, 114, 132, 116, 101, 115, 116, 132, 116, 101, 115, 116}) 294 | NewDecoderBytes(buf).Options(opt).Decode(&tmp) 295 | So(tmp, ShouldResemble, val) 296 | }) 297 | 298 | Convey("Can create map[time.Time]interface{} map type", t, func() { 299 | var tmp interface{} 300 | var buf []byte 301 | var val = map[time.Time]interface{}{tme: "test", jim: "other"} 302 | var opt = &Handle{SortMaps: true, MapType: make(map[time.Time]interface{})} 303 | NewEncoderBytes(&buf).Options(opt).Encode(val) 304 | So(buf, ShouldResemble, []byte{210, 227, 6, 187, 245, 101, 66, 48, 205, 21, 133, 111, 116, 104, 101, 114, 227, 7, 166, 199, 91, 123, 67, 205, 21, 132, 116, 101, 115, 116}) 305 | NewDecoderBytes(buf).Options(opt).Decode(&tmp) 306 | So(tmp, ShouldResemble, val) 307 | }) 308 | 309 | Convey("Can create map[interface{}]interface{} map type", t, func() { 310 | var tmp interface{} 311 | var buf []byte 312 | var val = map[interface{}]interface{}{tme: "test", 1: true, math.Pi: 3} 313 | var opt = &Handle{SortMaps: true, MapType: make(map[interface{}]interface{})} 314 | NewEncoderBytes(&buf).Options(opt).Encode(val) 315 | So(buf, ShouldResemble, []byte{211, 1, 225, 227, 7, 166, 199, 91, 123, 67, 205, 21, 132, 116, 101, 115, 116, 249, 64, 9, 33, 251, 84, 68, 45, 24, 3}) 316 | NewDecoderBytes(buf).Options(opt).Decode(&tmp) 317 | So(tmp, ShouldResemble, val) 318 | }) 319 | 320 | Convey("Can create reflect map type", t, func() { 321 | var tmp interface{} 322 | var buf []byte 323 | var val = map[string]Tested{"test": {Data: []byte("test"), Test: map[string]string{}, Temp: []string{}}, "other": {Data: []byte("other"), Test: map[string]string{}, Temp: []string{}}} 324 | var opt = &Handle{SortMaps: true, MapType: reflect.TypeOf(val)} 325 | NewEncoderBytes(&buf).Options(opt).Encode(val) 326 | So(buf, ShouldResemble, []byte{210, 132, 116, 101, 115, 116, 213, 132, 78, 97, 109, 101, 128, 132, 100, 97, 116, 97, 164, 116, 101, 115, 116, 132, 84, 101, 109, 112, 192, 132, 84, 101, 115, 116, 208, 133, 67, 111, 117, 110, 116, 0, 133, 111, 116, 104, 101, 114, 213, 132, 78, 97, 109, 101, 128, 132, 100, 97, 116, 97, 165, 111, 116, 104, 101, 114, 132, 84, 101, 109, 112, 192, 132, 84, 101, 115, 116, 208, 133, 67, 111, 117, 110, 116, 0}) 327 | NewDecoderBytes(buf).Options(opt).Decode(&tmp) 328 | So(tmp, ShouldResemble, val) 329 | }) 330 | 331 | } 332 | -------------------------------------------------------------------------------- /limits_test.go: -------------------------------------------------------------------------------- 1 | // Copyright © SurrealDB Ltd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package cork 16 | 17 | import ( 18 | "fmt" 19 | "math" 20 | "testing" 21 | 22 | . "github.com/smartystreets/goconvey/convey" 23 | ) 24 | 25 | func TestLimits(t *testing.T) { 26 | 27 | var sizes = []uint{1, 127, 128, math.MaxUint8, math.MaxUint8 + 1, math.MaxUint16, math.MaxUint16 + 1} 28 | 29 | Convey("Can create larger types", t, func() { 30 | 31 | for _, l := range sizes { 32 | 33 | Convey(fmt.Sprintf("Can encode map of length %d", l), func() { 34 | 35 | var bit []byte 36 | var val = make(map[uint]interface{}) 37 | var tmp = make(map[uint]interface{}) 38 | 39 | for i := uint(0); i < l; i++ { 40 | val[i] = nil 41 | } 42 | 43 | enc := NewEncoderBytes(&bit) 44 | eer := enc.Encode(val) 45 | So(eer, ShouldBeNil) 46 | 47 | dec := NewDecoderBytes(bit) 48 | der := dec.Decode(&tmp) 49 | So(der, ShouldBeNil) 50 | 51 | So(tmp, ShouldResemble, val) 52 | 53 | }) 54 | 55 | Convey(fmt.Sprintf("Can encode array of length %d", l), func() { 56 | 57 | var bit []byte 58 | var val = make([]interface{}, 0) 59 | var tmp = make([]interface{}, 0) 60 | 61 | for i := uint(0); i < l; i++ { 62 | val = append(val, nil) 63 | } 64 | 65 | enc := NewEncoderBytes(&bit) 66 | eer := enc.Encode(val) 67 | So(eer, ShouldBeNil) 68 | 69 | dec := NewDecoderBytes(bit) 70 | der := dec.Decode(&tmp) 71 | So(der, ShouldBeNil) 72 | 73 | So(tmp, ShouldResemble, val) 74 | 75 | }) 76 | 77 | } 78 | 79 | }) 80 | 81 | } 82 | -------------------------------------------------------------------------------- /reader.go: -------------------------------------------------------------------------------- 1 | // Copyright © SurrealDB Ltd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package cork 16 | 17 | import ( 18 | "encoding/binary" 19 | "math" 20 | "reflect" 21 | "time" 22 | 23 | "github.com/surrealdb/bump" 24 | ) 25 | 26 | // Reader is used when self-decoding a cork.Selfer item from binary form. 27 | type Reader struct { 28 | h *Handle 29 | r *bump.Reader 30 | } 31 | 32 | func newReader() *Reader { 33 | return &Reader{ 34 | r: bump.NewReader(nil), 35 | } 36 | } 37 | 38 | func (r *Reader) peekOne() (val byte) { 39 | val, err := r.r.PeekByte() 40 | if err != nil { 41 | panic(err) 42 | } 43 | return val 44 | } 45 | 46 | func (r *Reader) readOne() (val byte) { 47 | val, err := r.r.ReadByte() 48 | if err != nil { 49 | panic(err) 50 | } 51 | return val 52 | } 53 | 54 | func (r *Reader) readMany(l int) (val []byte) { 55 | val, err := r.r.ReadBytes(l) 56 | if err != nil { 57 | panic(err) 58 | } 59 | return val 60 | } 61 | 62 | func (r *Reader) readText(l int) (val string) { 63 | val, err := r.r.ReadString(l) 64 | if err != nil { 65 | panic(err) 66 | } 67 | return val 68 | } 69 | 70 | // --------------------------------------------------------------------------- 71 | 72 | func (r *Reader) readLen() int { 73 | b := r.readOne() 74 | switch { 75 | case b >= cFixInt && b <= cFixInt+fixedInt: 76 | return int(b) 77 | case b == cUint8: 78 | return int(r.readOne()) 79 | case b == cUint16: 80 | return int(binary.BigEndian.Uint16(r.readMany(2))) 81 | case b == cUint32: 82 | return int(binary.BigEndian.Uint32(r.readMany(4))) 83 | case b == cUint64: 84 | return int(binary.BigEndian.Uint64(r.readMany(8))) 85 | default: 86 | panic(fail) 87 | } 88 | } 89 | 90 | func (r *Reader) readLen8() int { 91 | return int(r.readOne()) 92 | } 93 | 94 | func (r *Reader) readLen16() int { 95 | return int(binary.BigEndian.Uint16(r.readMany(2))) 96 | } 97 | 98 | func (r *Reader) readLen32() int { 99 | return int(binary.BigEndian.Uint32(r.readMany(4))) 100 | } 101 | 102 | func (r *Reader) readLen64() int { 103 | return int(binary.BigEndian.Uint64(r.readMany(8))) 104 | } 105 | 106 | // --------------------------------------------------------------------------- 107 | 108 | // DecodeBool decodes a boolean value from the Reader. 109 | func (r *Reader) DecodeBool(v *bool) { 110 | switch r.readOne() { 111 | case cTrue: 112 | *v = true 113 | case cFalse: 114 | *v = false 115 | default: 116 | panic(fail) 117 | } 118 | } 119 | 120 | // DecodeByte decodes a byte value from the Reader. 121 | func (r *Reader) DecodeByte(v *byte) { 122 | *v = r.readOne() 123 | } 124 | 125 | // DecodeBytes decodes a byte slice value from the Reader. 126 | func (r *Reader) DecodeBytes(v *[]byte) { 127 | b := r.readOne() 128 | switch { 129 | case b >= cFixBin && b <= cFixBin+fixedBin: 130 | *v = r.readMany(int(b - cFixBin)) 131 | case b == cBin8: 132 | *v = r.readMany(int(r.readLen8())) 133 | case b == cBin16: 134 | *v = r.readMany(int(r.readLen16())) 135 | case b == cBin32: 136 | *v = r.readMany(int(r.readLen32())) 137 | case b == cBin64: 138 | *v = r.readMany(int(r.readLen64())) 139 | default: 140 | panic(fail) 141 | } 142 | } 143 | 144 | // DecodeString decodes a string value from the Reader. 145 | func (r *Reader) DecodeString(v *string) { 146 | b := r.readOne() 147 | switch { 148 | case b >= cFixStr && b <= cFixStr+fixedStr: 149 | *v = r.readText(int(b - cFixStr)) 150 | case b == cStr8: 151 | *v = r.readText(int(r.readLen8())) 152 | case b == cStr16: 153 | *v = r.readText(int(r.readLen16())) 154 | case b == cStr32: 155 | *v = r.readText(int(r.readLen32())) 156 | case b == cStr64: 157 | *v = r.readText(int(r.readLen64())) 158 | default: 159 | panic(fail) 160 | } 161 | } 162 | 163 | // --------------------------------------------------------------------------- 164 | 165 | // DecodeInt decodes an int value from the Reader. 166 | func (r *Reader) DecodeInt(v *int) { 167 | b := r.readOne() 168 | switch { 169 | case b >= cFixInt && b <= cFixInt+fixedInt: 170 | *v = int(b) 171 | case b == cInt8: 172 | *v = int(int8(r.readOne())) 173 | case b == cInt16: 174 | *v = int(int16(binary.BigEndian.Uint16(r.readMany(2)))) 175 | case b == cInt32: 176 | *v = int(int32(binary.BigEndian.Uint32(r.readMany(4)))) 177 | case b == cInt64: 178 | *v = int(int64(binary.BigEndian.Uint64(r.readMany(8)))) 179 | default: 180 | panic(fail) 181 | } 182 | } 183 | 184 | // DecodeInt8 decodes an int8 value from the Reader. 185 | func (r *Reader) DecodeInt8(v *int8) { 186 | b := r.readOne() 187 | switch { 188 | case b >= cFixInt && b <= cFixInt+fixedInt: 189 | *v = int8(b) 190 | case b == cInt8: 191 | *v = int8(r.readOne()) 192 | default: 193 | panic(fail) 194 | } 195 | } 196 | 197 | // DecodeInt16 decodes an int16 value from the Reader. 198 | func (r *Reader) DecodeInt16(v *int16) { 199 | b := r.readOne() 200 | switch { 201 | case b >= cFixInt && b <= cFixInt+fixedInt: 202 | *v = int16(b) 203 | case b == cInt8: 204 | *v = int16(int8(r.readOne())) 205 | case b == cInt16: 206 | *v = int16(binary.BigEndian.Uint16(r.readMany(2))) 207 | default: 208 | panic(fail) 209 | } 210 | } 211 | 212 | // DecodeInt32 decodes an int32 value from the Reader. 213 | func (r *Reader) DecodeInt32(v *int32) { 214 | b := r.readOne() 215 | switch { 216 | case b >= cFixInt && b <= cFixInt+fixedInt: 217 | *v = int32(b) 218 | case b == cInt8: 219 | *v = int32(int8(r.readOne())) 220 | case b == cInt16: 221 | *v = int32(int16(binary.BigEndian.Uint16(r.readMany(2)))) 222 | case b == cInt32: 223 | *v = int32(binary.BigEndian.Uint32(r.readMany(4))) 224 | default: 225 | panic(fail) 226 | } 227 | } 228 | 229 | // DecodeInt64 decodes an int64 value from the Reader. 230 | func (r *Reader) DecodeInt64(v *int64) { 231 | b := r.readOne() 232 | switch { 233 | case b >= cFixInt && b <= cFixInt+fixedInt: 234 | *v = int64(b) 235 | case b == cInt8: 236 | *v = int64(int8(r.readOne())) 237 | case b == cInt16: 238 | *v = int64(int16(binary.BigEndian.Uint16(r.readMany(2)))) 239 | case b == cInt32: 240 | *v = int64(int32(binary.BigEndian.Uint32(r.readMany(4)))) 241 | case b == cInt64: 242 | *v = int64(binary.BigEndian.Uint64(r.readMany(8))) 243 | default: 244 | panic(fail) 245 | } 246 | } 247 | 248 | // --------------------------------------------------------------------------- 249 | 250 | // DecodeUint decodes a uint value from the Reader. 251 | func (r *Reader) DecodeUint(v *uint) { 252 | b := r.readOne() 253 | switch { 254 | case b >= cFixInt && b <= cFixInt+fixedInt: 255 | *v = uint(b) 256 | case b == cUint8: 257 | *v = uint(r.readOne()) 258 | case b == cUint16: 259 | *v = uint(binary.BigEndian.Uint16(r.readMany(2))) 260 | case b == cUint32: 261 | *v = uint(binary.BigEndian.Uint32(r.readMany(4))) 262 | case b == cUint64: 263 | *v = uint(binary.BigEndian.Uint64(r.readMany(8))) 264 | default: 265 | panic(fail) 266 | } 267 | } 268 | 269 | // DecodeUint8 decodes a uint8 value from the Reader. 270 | func (r *Reader) DecodeUint8(v *uint8) { 271 | b := r.readOne() 272 | switch { 273 | case b >= cFixInt && b <= cFixInt+fixedInt: 274 | *v = uint8(b) 275 | case b == cUint8: 276 | *v = uint8(r.readOne()) 277 | default: 278 | panic(fail) 279 | } 280 | } 281 | 282 | // DecodeUint16 decodes a uint16 value from the Reader. 283 | func (r *Reader) DecodeUint16(v *uint16) { 284 | b := r.readOne() 285 | switch { 286 | case b >= cFixInt && b <= cFixInt+fixedInt: 287 | *v = uint16(b) 288 | case b == cUint8: 289 | *v = uint16(r.readOne()) 290 | case b == cUint16: 291 | *v = uint16(binary.BigEndian.Uint16(r.readMany(2))) 292 | default: 293 | panic(fail) 294 | } 295 | } 296 | 297 | // DecodeUint32 decodes a uint32 value from the Reader. 298 | func (r *Reader) DecodeUint32(v *uint32) { 299 | b := r.readOne() 300 | switch { 301 | case b >= cFixInt && b <= cFixInt+fixedInt: 302 | *v = uint32(b) 303 | case b == cUint8: 304 | *v = uint32(r.readOne()) 305 | case b == cUint16: 306 | *v = uint32(binary.BigEndian.Uint16(r.readMany(2))) 307 | case b == cUint32: 308 | *v = uint32(binary.BigEndian.Uint32(r.readMany(4))) 309 | default: 310 | panic(fail) 311 | } 312 | } 313 | 314 | // DecodeUint64 decodes a uint64 value from the Reader. 315 | func (r *Reader) DecodeUint64(v *uint64) { 316 | b := r.readOne() 317 | switch { 318 | case b >= cFixInt && b <= cFixInt+fixedInt: 319 | *v = uint64(b) 320 | case b == cUint8: 321 | *v = uint64(r.readOne()) 322 | case b == cUint16: 323 | *v = uint64(binary.BigEndian.Uint16(r.readMany(2))) 324 | case b == cUint32: 325 | *v = uint64(binary.BigEndian.Uint32(r.readMany(4))) 326 | case b == cUint64: 327 | *v = uint64(binary.BigEndian.Uint64(r.readMany(8))) 328 | default: 329 | panic(fail) 330 | } 331 | } 332 | 333 | // --------------------------------------------------------------------------- 334 | 335 | // DecodeFloat32 decodes a float32 value from the Reader. 336 | func (r *Reader) DecodeFloat32(v *float32) { 337 | if r.readOne() == cFloat32 { 338 | b := binary.BigEndian.Uint32(r.readMany(4)) 339 | *v = math.Float32frombits(b) 340 | return 341 | } 342 | panic(fail) 343 | } 344 | 345 | // DecodeFloat64 decodes a float64 value from the Reader. 346 | func (r *Reader) DecodeFloat64(v *float64) { 347 | switch r.readOne() { 348 | case cFloat32: 349 | b := binary.BigEndian.Uint32(r.readMany(4)) 350 | *v = float64(math.Float32frombits(b)) 351 | case cFloat64: 352 | b := uint64(binary.BigEndian.Uint64(r.readMany(8))) 353 | *v = math.Float64frombits(b) 354 | default: 355 | panic(fail) 356 | } 357 | } 358 | 359 | // --------------------------------------------------------------------------- 360 | 361 | // DecodeComplex64 decodes a complex64 value from the Reader. 362 | func (r *Reader) DecodeComplex64(v *complex64) { 363 | if r.readOne() == cComplex64 { 364 | one := binary.BigEndian.Uint32(r.readMany(4)) 365 | two := binary.BigEndian.Uint32(r.readMany(4)) 366 | *v = complex(math.Float32frombits(one), math.Float32frombits(two)) 367 | return 368 | } 369 | panic(fail) 370 | } 371 | 372 | // DecodeComplex128 decodes a complex128 value from the Reader. 373 | func (r *Reader) DecodeComplex128(v *complex128) { 374 | if r.readOne() == cComplex128 { 375 | one := binary.BigEndian.Uint64(r.readMany(8)) 376 | two := binary.BigEndian.Uint64(r.readMany(8)) 377 | *v = complex(math.Float64frombits(one), math.Float64frombits(two)) 378 | return 379 | } 380 | panic(fail) 381 | } 382 | 383 | // --------------------------------------------------------------------------- 384 | 385 | // DecodeTime decodes a time.Time value from the Reader. 386 | func (r *Reader) DecodeTime(v *time.Time) { 387 | if r.readOne() == cTime { 388 | b := int64(binary.BigEndian.Uint64(r.readMany(8))) 389 | *v = time.Unix(0, b).UTC() 390 | return 391 | } 392 | panic(fail) 393 | } 394 | 395 | // --------------------------------------------------------------------------- 396 | 397 | // DecodeArr decodes an array from the Reader. 398 | func (r *Reader) DecodeArr(v interface{}) { 399 | switch a := v.(type) { 400 | case *[]bool: 401 | r.decodeArrBool(a) 402 | case *[]int: 403 | r.decodeArrInt(a) 404 | case *[]int8: 405 | r.decodeArrInt8(a) 406 | case *[]int16: 407 | r.decodeArrInt16(a) 408 | case *[]int32: 409 | r.decodeArrInt32(a) 410 | case *[]int64: 411 | r.decodeArrInt64(a) 412 | case *[]uint: 413 | r.decodeArrUint(a) 414 | case *[]uint8: 415 | r.decodeArrUint8(a) 416 | case *[]uint16: 417 | r.decodeArrUint16(a) 418 | case *[]uint32: 419 | r.decodeArrUint32(a) 420 | case *[]uint64: 421 | r.decodeArrUint64(a) 422 | case *[]string: 423 | r.decodeArrString(a) 424 | case *[]float32: 425 | r.decodeArrFloat32(a) 426 | case *[]float64: 427 | r.decodeArrFloat64(a) 428 | case *[]complex64: 429 | r.decodeArrComplex64(a) 430 | case *[]complex128: 431 | r.decodeArrComplex128(a) 432 | case *[]time.Time: 433 | r.decodeArrTime(a) 434 | case *[]interface{}: 435 | r.decodeArrAny(a) 436 | case reflect.Value: 437 | r.decodeArr(a) 438 | default: 439 | r.DecodeAny(v) 440 | } 441 | } 442 | 443 | func (r *Reader) decodeArrLen() int { 444 | b := r.readOne() 445 | switch { 446 | case b >= cFixArr && b <= cFixArr+fixedArr: 447 | return int(b - cFixArr) 448 | case b == cArr: 449 | return r.readLen() 450 | default: 451 | panic(fail) 452 | } 453 | } 454 | 455 | // DecodeMap decodes a map from the Reader. 456 | func (r *Reader) DecodeMap(v interface{}) { 457 | switch m := v.(type) { 458 | case *map[string]int: 459 | r.decodeMapStringInt(m) 460 | case *map[string]uint: 461 | r.decodeMapStringUint(m) 462 | case *map[string]bool: 463 | r.decodeMapStringBool(m) 464 | case *map[string]string: 465 | r.decodeMapStringString(m) 466 | case *map[int]interface{}: 467 | r.decodeMapIntAny(m) 468 | case *map[uint]interface{}: 469 | r.decodeMapUintAny(m) 470 | case *map[string]interface{}: 471 | r.decodeMapStringAny(m) 472 | case *map[time.Time]interface{}: 473 | r.decodeMapTimeAny(m) 474 | case *map[interface{}]interface{}: 475 | r.decodeMapAnyAny(m) 476 | case reflect.Value: 477 | r.decodeMap(m) 478 | default: 479 | r.DecodeAny(v) 480 | } 481 | } 482 | 483 | func (r *Reader) decodeMapLen() int { 484 | b := r.readOne() 485 | switch { 486 | case b >= cFixMap && b <= cFixMap+fixedMap: 487 | return int(b - cFixMap) 488 | case b == cMap: 489 | return r.readLen() 490 | default: 491 | panic(fail) 492 | } 493 | } 494 | -------------------------------------------------------------------------------- /reader_any.go: -------------------------------------------------------------------------------- 1 | // Copyright © SurrealDB Ltd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://wwr.deache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package cork 16 | 17 | import ( 18 | "encoding" 19 | "reflect" 20 | "time" 21 | ) 22 | 23 | // DecodeAny decodes a value from the Reader. 24 | func (r *Reader) DecodeAny(v interface{}) { 25 | 26 | switch v := v.(type) { 27 | 28 | case Selfer: 29 | r.DecodeSelfer(v) 30 | case Corker: 31 | r.DecodeCorker(v) 32 | 33 | // ------------------------- 34 | 35 | case *bool: 36 | r.DecodeBool(v) 37 | case *byte: 38 | r.DecodeByte(v) 39 | case *[]byte: 40 | r.DecodeBytes(v) 41 | case *string: 42 | r.DecodeString(v) 43 | case *int: 44 | r.DecodeInt(v) 45 | case *int8: 46 | r.DecodeInt8(v) 47 | case *int16: 48 | r.DecodeInt16(v) 49 | case *int32: 50 | r.DecodeInt32(v) 51 | case *int64: 52 | r.DecodeInt64(v) 53 | case *uint: 54 | r.DecodeUint(v) 55 | case *uint16: 56 | r.DecodeUint16(v) 57 | case *uint32: 58 | r.DecodeUint32(v) 59 | case *uint64: 60 | r.DecodeUint64(v) 61 | case *float32: 62 | r.DecodeFloat32(v) 63 | case *float64: 64 | r.DecodeFloat64(v) 65 | case *complex64: 66 | r.DecodeComplex64(v) 67 | case *complex128: 68 | r.DecodeComplex128(v) 69 | case *time.Time: 70 | r.DecodeTime(v) 71 | 72 | // ------------------------- 73 | 74 | case *[]bool: 75 | r.decodeArrBool(v) 76 | case *[]int: 77 | r.decodeArrInt(v) 78 | case *[]int8: 79 | r.decodeArrInt8(v) 80 | case *[]int16: 81 | r.decodeArrInt16(v) 82 | case *[]int32: 83 | r.decodeArrInt32(v) 84 | case *[]int64: 85 | r.decodeArrInt64(v) 86 | case *[]uint: 87 | r.decodeArrUint(v) 88 | case *[]uint16: 89 | r.decodeArrUint16(v) 90 | case *[]uint32: 91 | r.decodeArrUint32(v) 92 | case *[]uint64: 93 | r.decodeArrUint64(v) 94 | case *[]string: 95 | r.decodeArrString(v) 96 | case *[]float32: 97 | r.decodeArrFloat32(v) 98 | case *[]float64: 99 | r.decodeArrFloat64(v) 100 | case *[]complex64: 101 | r.decodeArrComplex64(v) 102 | case *[]complex128: 103 | r.decodeArrComplex128(v) 104 | case *[]time.Time: 105 | r.decodeArrTime(v) 106 | case *[]interface{}: 107 | r.decodeArrAny(v) 108 | 109 | // ------------------------- 110 | 111 | case *map[string]int: 112 | r.decodeMapStringInt(v) 113 | case *map[string]uint: 114 | r.decodeMapStringUint(v) 115 | case *map[string]bool: 116 | r.decodeMapStringBool(v) 117 | case *map[string]string: 118 | r.decodeMapStringString(v) 119 | case *map[int]interface{}: 120 | r.decodeMapIntAny(v) 121 | case *map[uint]interface{}: 122 | r.decodeMapUintAny(v) 123 | case *map[string]interface{}: 124 | r.decodeMapStringAny(v) 125 | case *map[time.Time]interface{}: 126 | r.decodeMapTimeAny(v) 127 | case *map[interface{}]interface{}: 128 | r.decodeMapAnyAny(v) 129 | 130 | // ------------------------- 131 | 132 | case *interface{}: 133 | r.DecodeInterface(v) 134 | 135 | // ------------------------- 136 | 137 | case encoding.BinaryUnmarshaler: 138 | var enc []byte 139 | r.DecodeBytes(&enc) 140 | err := v.UnmarshalBinary(enc) 141 | if err != nil { 142 | panic(err) 143 | } 144 | 145 | case encoding.TextUnmarshaler: 146 | var enc []byte 147 | r.DecodeBytes(&enc) 148 | err := v.UnmarshalText(enc) 149 | if err != nil { 150 | panic(err) 151 | } 152 | 153 | default: 154 | r.DecodeReflect(reflect.ValueOf(v)) 155 | 156 | } 157 | 158 | } 159 | -------------------------------------------------------------------------------- /reader_arr.go: -------------------------------------------------------------------------------- 1 | // Copyright © SurrealDB Ltd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package cork 16 | 17 | import ( 18 | "reflect" 19 | "time" 20 | ) 21 | 22 | func (r *Reader) decodeArr(a reflect.Value) { 23 | t := a.Type() 24 | s := r.decodeArrLen() 25 | if a.IsNil() || a.Len() < s { 26 | a.Set(reflect.MakeSlice(t, s, s)) 27 | } 28 | for i := 0; i < s; i++ { 29 | r.DecodeReflect(a.Index(i)) 30 | } 31 | } 32 | 33 | func (r *Reader) decodeArrBool(a *[]bool) { 34 | s := r.decodeArrLen() 35 | if *a == nil || len(*a) < s { 36 | *a = make([]bool, s) 37 | } 38 | for i := 0; i < s; i++ { 39 | r.DecodeBool(&(*a)[i]) 40 | } 41 | } 42 | 43 | func (r *Reader) decodeArrInt(a *[]int) { 44 | s := r.decodeArrLen() 45 | if *a == nil || len(*a) < s { 46 | *a = make([]int, s) 47 | } 48 | for i := 0; i < s; i++ { 49 | r.DecodeInt(&(*a)[i]) 50 | } 51 | } 52 | 53 | func (r *Reader) decodeArrInt8(a *[]int8) { 54 | s := r.decodeArrLen() 55 | if *a == nil || len(*a) < s { 56 | *a = make([]int8, s) 57 | } 58 | for i := 0; i < s; i++ { 59 | r.DecodeInt8(&(*a)[i]) 60 | } 61 | } 62 | 63 | func (r *Reader) decodeArrInt16(a *[]int16) { 64 | s := r.decodeArrLen() 65 | if *a == nil || len(*a) < s { 66 | *a = make([]int16, s) 67 | } 68 | for i := 0; i < s; i++ { 69 | r.DecodeInt16(&(*a)[i]) 70 | } 71 | } 72 | 73 | func (r *Reader) decodeArrInt32(a *[]int32) { 74 | s := r.decodeArrLen() 75 | if *a == nil || len(*a) < s { 76 | *a = make([]int32, s) 77 | } 78 | for i := 0; i < s; i++ { 79 | r.DecodeInt32(&(*a)[i]) 80 | } 81 | } 82 | 83 | func (r *Reader) decodeArrInt64(a *[]int64) { 84 | s := r.decodeArrLen() 85 | if *a == nil || len(*a) < s { 86 | *a = make([]int64, s) 87 | } 88 | for i := 0; i < s; i++ { 89 | r.DecodeInt64(&(*a)[i]) 90 | } 91 | } 92 | 93 | func (r *Reader) decodeArrUint(a *[]uint) { 94 | s := r.decodeArrLen() 95 | if *a == nil || len(*a) < s { 96 | *a = make([]uint, s) 97 | } 98 | for i := 0; i < s; i++ { 99 | r.DecodeUint(&(*a)[i]) 100 | } 101 | } 102 | 103 | func (r *Reader) decodeArrUint8(a *[]uint8) { 104 | s := r.decodeArrLen() 105 | if *a == nil || len(*a) < s { 106 | *a = make([]uint8, s) 107 | } 108 | for i := 0; i < s; i++ { 109 | r.DecodeUint8(&(*a)[i]) 110 | } 111 | } 112 | 113 | func (r *Reader) decodeArrUint16(a *[]uint16) { 114 | s := r.decodeArrLen() 115 | if *a == nil || len(*a) < s { 116 | *a = make([]uint16, s) 117 | } 118 | for i := 0; i < s; i++ { 119 | r.DecodeUint16(&(*a)[i]) 120 | } 121 | } 122 | 123 | func (r *Reader) decodeArrUint32(a *[]uint32) { 124 | s := r.decodeArrLen() 125 | if *a == nil || len(*a) < s { 126 | *a = make([]uint32, s) 127 | } 128 | for i := 0; i < s; i++ { 129 | r.DecodeUint32(&(*a)[i]) 130 | } 131 | } 132 | 133 | func (r *Reader) decodeArrUint64(a *[]uint64) { 134 | s := r.decodeArrLen() 135 | if *a == nil || len(*a) < s { 136 | *a = make([]uint64, s) 137 | } 138 | for i := 0; i < s; i++ { 139 | r.DecodeUint64(&(*a)[i]) 140 | } 141 | } 142 | 143 | func (r *Reader) decodeArrString(a *[]string) { 144 | s := r.decodeArrLen() 145 | if *a == nil || len(*a) < s { 146 | *a = make([]string, s) 147 | } 148 | for i := 0; i < s; i++ { 149 | r.DecodeString(&(*a)[i]) 150 | } 151 | } 152 | 153 | func (r *Reader) decodeArrFloat32(a *[]float32) { 154 | s := r.decodeArrLen() 155 | if *a == nil || len(*a) < s { 156 | *a = make([]float32, s) 157 | } 158 | for i := 0; i < s; i++ { 159 | r.DecodeFloat32(&(*a)[i]) 160 | } 161 | } 162 | 163 | func (r *Reader) decodeArrFloat64(a *[]float64) { 164 | s := r.decodeArrLen() 165 | if *a == nil || len(*a) < s { 166 | *a = make([]float64, s) 167 | } 168 | for i := 0; i < s; i++ { 169 | r.DecodeFloat64(&(*a)[i]) 170 | } 171 | } 172 | 173 | func (r *Reader) decodeArrComplex64(a *[]complex64) { 174 | s := r.decodeArrLen() 175 | if *a == nil || len(*a) < s { 176 | *a = make([]complex64, s) 177 | } 178 | for i := 0; i < s; i++ { 179 | r.DecodeComplex64(&(*a)[i]) 180 | } 181 | } 182 | 183 | func (r *Reader) decodeArrComplex128(a *[]complex128) { 184 | s := r.decodeArrLen() 185 | if *a == nil || len(*a) < s { 186 | *a = make([]complex128, s) 187 | } 188 | for i := 0; i < s; i++ { 189 | r.DecodeComplex128(&(*a)[i]) 190 | } 191 | } 192 | 193 | func (r *Reader) decodeArrTime(a *[]time.Time) { 194 | s := r.decodeArrLen() 195 | if *a == nil || len(*a) < s { 196 | *a = make([]time.Time, s) 197 | } 198 | for i := 0; i < s; i++ { 199 | r.DecodeTime(&(*a)[i]) 200 | } 201 | } 202 | 203 | func (r *Reader) decodeArrAny(a *[]interface{}) { 204 | s := r.decodeArrLen() 205 | if *a == nil || len(*a) < s { 206 | *a = make([]interface{}, s) 207 | } 208 | for i := 0; i < s; i++ { 209 | r.DecodeAny(&(*a)[i]) 210 | } 211 | } 212 | -------------------------------------------------------------------------------- /reader_ext.go: -------------------------------------------------------------------------------- 1 | // Copyright © SurrealDB Ltd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package cork 16 | 17 | // DecodeSelfer decodes a cork.Selfer value from the Reader. 18 | func (r *Reader) DecodeSelfer(v Selfer) { 19 | if r.readOne() == cSlf { 20 | if r.readOne() == v.ExtendCORK() { 21 | v.UnmarshalCORK(r) 22 | return 23 | } 24 | } 25 | panic(fail) 26 | } 27 | 28 | // DecodeCorker decodes a cork.Corker value from the Reader. 29 | func (r *Reader) DecodeCorker(v Corker) { 30 | b := r.readOne() 31 | var s int 32 | switch { 33 | case b >= cFixExt && b <= cFixExt+fixedExt: 34 | s = int(b - cFixExt) 35 | case b == cExt8: 36 | s = int(r.readLen8()) 37 | case b == cExt16: 38 | s = int(r.readLen16()) 39 | case b == cExt32: 40 | s = int(r.readLen32()) 41 | case b == cExt64: 42 | s = int(r.readLen64()) 43 | default: 44 | panic(fail) 45 | } 46 | if r.readOne() != v.ExtendCORK() { 47 | panic(fail) 48 | } 49 | if err := v.UnmarshalCORK(r.readMany(s)); err != nil { 50 | panic(err) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /reader_map.go: -------------------------------------------------------------------------------- 1 | // Copyright © SurrealDB Ltd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package cork 16 | 17 | import ( 18 | "reflect" 19 | "time" 20 | ) 21 | 22 | func (r *Reader) decodeMap(m reflect.Value) { 23 | t := m.Type() 24 | s := r.decodeMapLen() 25 | if m.IsNil() { 26 | m.Set(reflect.MakeMap(t)) 27 | } 28 | for i := 0; i < s; i++ { 29 | k := reflect.New(t.Key()) 30 | r.DecodeReflect(k) 31 | v := reflect.New(t.Elem()) 32 | r.DecodeReflect(v) 33 | m.SetMapIndex(k.Elem(), v.Elem()) 34 | } 35 | } 36 | 37 | func (r *Reader) decodeMapStringInt(m *map[string]int) { 38 | s := r.decodeMapLen() 39 | if *m == nil { 40 | *m = make(map[string]int, s) 41 | } 42 | for i := 0; i < s; i++ { 43 | var k string 44 | var v int 45 | r.DecodeString(&k) 46 | r.DecodeInt(&v) 47 | (*m)[k] = v 48 | } 49 | } 50 | 51 | func (r *Reader) decodeMapStringUint(m *map[string]uint) { 52 | s := r.decodeMapLen() 53 | if *m == nil { 54 | *m = make(map[string]uint, s) 55 | } 56 | for i := 0; i < s; i++ { 57 | var k string 58 | var v uint 59 | r.DecodeString(&k) 60 | r.DecodeUint(&v) 61 | (*m)[k] = v 62 | } 63 | } 64 | 65 | func (r *Reader) decodeMapStringBool(m *map[string]bool) { 66 | s := r.decodeMapLen() 67 | if *m == nil { 68 | *m = make(map[string]bool, s) 69 | } 70 | for i := 0; i < s; i++ { 71 | var k string 72 | var v bool 73 | r.DecodeString(&k) 74 | r.DecodeBool(&v) 75 | (*m)[k] = v 76 | } 77 | } 78 | 79 | func (r *Reader) decodeMapStringString(m *map[string]string) { 80 | s := r.decodeMapLen() 81 | if *m == nil { 82 | *m = make(map[string]string, s) 83 | } 84 | for i := 0; i < s; i++ { 85 | var k string 86 | var v string 87 | r.DecodeString(&k) 88 | r.DecodeString(&v) 89 | (*m)[k] = v 90 | } 91 | } 92 | 93 | func (r *Reader) decodeMapIntAny(m *map[int]interface{}) { 94 | s := r.decodeMapLen() 95 | if *m == nil { 96 | *m = make(map[int]interface{}, s) 97 | } 98 | for i := 0; i < s; i++ { 99 | var k int 100 | var v interface{} 101 | r.DecodeInt(&k) 102 | r.DecodeAny(&v) 103 | (*m)[k] = v 104 | } 105 | } 106 | 107 | func (r *Reader) decodeMapUintAny(m *map[uint]interface{}) { 108 | s := r.decodeMapLen() 109 | if *m == nil { 110 | *m = make(map[uint]interface{}, s) 111 | } 112 | for i := 0; i < s; i++ { 113 | var k uint 114 | var v interface{} 115 | r.DecodeUint(&k) 116 | r.DecodeAny(&v) 117 | (*m)[k] = v 118 | } 119 | } 120 | 121 | func (r *Reader) decodeMapStringAny(m *map[string]interface{}) { 122 | s := r.decodeMapLen() 123 | if *m == nil { 124 | *m = make(map[string]interface{}, s) 125 | } 126 | for i := 0; i < s; i++ { 127 | var k string 128 | var v interface{} 129 | r.DecodeString(&k) 130 | r.DecodeAny(&v) 131 | (*m)[k] = v 132 | } 133 | } 134 | 135 | func (r *Reader) decodeMapTimeAny(m *map[time.Time]interface{}) { 136 | s := r.decodeMapLen() 137 | if *m == nil { 138 | *m = make(map[time.Time]interface{}, s) 139 | } 140 | for i := 0; i < s; i++ { 141 | var k time.Time 142 | var v interface{} 143 | r.DecodeTime(&k) 144 | r.DecodeAny(&v) 145 | (*m)[k] = v 146 | } 147 | } 148 | 149 | func (r *Reader) decodeMapAnyAny(m *map[interface{}]interface{}) { 150 | s := r.decodeMapLen() 151 | if *m == nil { 152 | *m = make(map[interface{}]interface{}, s) 153 | } 154 | for i := 0; i < s; i++ { 155 | var k interface{} 156 | var v interface{} 157 | r.DecodeAny(&k) 158 | r.DecodeAny(&v) 159 | (*m)[k] = v 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /reader_ref.go: -------------------------------------------------------------------------------- 1 | // Copyright © SurrealDB Ltd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package cork 16 | 17 | import ( 18 | "reflect" 19 | "time" 20 | ) 21 | 22 | // DecodeReflect decodes a reflect.Value value from the Reader. 23 | func (r *Reader) DecodeReflect(v reflect.Value) { 24 | 25 | b := r.peekOne() 26 | 27 | if b == cNil { 28 | r.readOne() 29 | return 30 | } 31 | 32 | t := v.Type() 33 | k := v.Kind() 34 | 35 | // First let's check to see if this is 36 | // a nil pointer, and if it is then we 37 | // will create a new value for the 38 | // underlying type, and set the pointer 39 | // to this value. 40 | 41 | if v.Kind() == reflect.Ptr && v.IsNil() { 42 | n := reflect.New(t.Elem()) 43 | v.Set(n) 44 | } 45 | 46 | // Next let's check to see if the type 47 | // implements either the Selfer or Corker 48 | // interfaces, and if it does then decode 49 | // it directly. Caching the interface 50 | // detection speeds up the decoding. 51 | 52 | if c.Selfable(t) { 53 | n := reflect.New(t.Elem()) 54 | r.DecodeSelfer(n.Interface().(Selfer)) 55 | v.Set(n) 56 | return 57 | } 58 | 59 | if c.Corkable(t) { 60 | n := reflect.New(t.Elem()) 61 | r.DecodeCorker(n.Interface().(Corker)) 62 | v.Set(n) 63 | return 64 | } 65 | 66 | // It wasn't a self describing interface 67 | // so let's now see if it is a string or 68 | // a byte slice, and if it is, then 69 | // decode it immediately. 70 | 71 | switch t { 72 | 73 | case typeStr: 74 | var x string 75 | r.DecodeString(&x) 76 | v.SetString(x) 77 | return 78 | 79 | case typeBit: 80 | var x []byte 81 | r.DecodeBytes(&x) 82 | v.SetBytes(x) 83 | return 84 | 85 | case typeTime: 86 | var x time.Time 87 | r.DecodeTime(&x) 88 | v.Set(reflect.ValueOf(x)) 89 | return 90 | 91 | } 92 | 93 | // Otherwise let's switch over all of the 94 | // possible types that this item can be 95 | // and decode it into the correct type. 96 | // For structs, we will cache the struct 97 | // fields, so that we do not have to parse 98 | // these for every item that we process. 99 | 100 | switch k { 101 | 102 | case reflect.Ptr: 103 | r.DecodeReflect(v.Elem()) 104 | 105 | case reflect.Map: 106 | r.decodeMap(v) 107 | 108 | case reflect.Slice: 109 | r.decodeArr(v) 110 | 111 | case reflect.Bool: 112 | var x bool 113 | r.DecodeBool(&x) 114 | v.SetBool(x) 115 | 116 | case reflect.String: 117 | var x string 118 | r.DecodeString(&x) 119 | v.SetString(x) 120 | 121 | case reflect.Int: 122 | var x int 123 | r.DecodeInt(&x) 124 | v.SetInt(int64(x)) 125 | 126 | case reflect.Int8: 127 | var x int8 128 | r.DecodeInt8(&x) 129 | v.SetInt(int64(x)) 130 | 131 | case reflect.Int16: 132 | var x int16 133 | r.DecodeInt16(&x) 134 | v.SetInt(int64(x)) 135 | 136 | case reflect.Int32: 137 | var x int32 138 | r.DecodeInt32(&x) 139 | v.SetInt(int64(x)) 140 | 141 | case reflect.Int64: 142 | var x int64 143 | r.DecodeInt64(&x) 144 | v.SetInt(x) 145 | 146 | case reflect.Uint: 147 | var x uint 148 | r.DecodeUint(&x) 149 | v.SetUint(uint64(x)) 150 | 151 | case reflect.Uint8: 152 | var x uint8 153 | r.DecodeUint8(&x) 154 | v.SetUint(uint64(x)) 155 | 156 | case reflect.Uint16: 157 | var x uint16 158 | r.DecodeUint16(&x) 159 | v.SetUint(uint64(x)) 160 | 161 | case reflect.Uint32: 162 | var x uint32 163 | r.DecodeUint32(&x) 164 | v.SetUint(uint64(x)) 165 | 166 | case reflect.Uint64: 167 | var x uint64 168 | r.DecodeUint64(&x) 169 | v.SetUint(x) 170 | 171 | case reflect.Float32: 172 | var x float32 173 | r.DecodeFloat32(&x) 174 | v.SetFloat(float64(x)) 175 | 176 | case reflect.Float64: 177 | var x float64 178 | r.DecodeFloat64(&x) 179 | v.SetFloat(x) 180 | 181 | case reflect.Complex64: 182 | var x complex64 183 | r.DecodeComplex64(&x) 184 | v.SetComplex(complex128(x)) 185 | 186 | case reflect.Complex128: 187 | var x complex128 188 | r.DecodeComplex128(&x) 189 | v.SetComplex(x) 190 | 191 | case reflect.Interface: 192 | var x interface{} 193 | r.DecodeInterface(&x) 194 | if reflect.ValueOf(x).IsValid() { 195 | v.Set(reflect.ValueOf(x)) 196 | } 197 | 198 | case reflect.Struct: 199 | 200 | if !c.Has(t) { 201 | tot := 0 202 | fls := make([]*field, t.NumField()) 203 | for i := 0; i < t.NumField(); i++ { 204 | if f := newField(t.Field(i)); f != nil { 205 | fls[tot] = f 206 | tot++ 207 | } 208 | } 209 | c.Set(t, fls[:tot]) 210 | } 211 | 212 | x := c.Get(t) 213 | s := r.decodeMapLen() 214 | 215 | for i := 0; i < s; i++ { 216 | 217 | var k string 218 | r.DecodeString(&k) 219 | 220 | for _, f := range x { 221 | if k == f.Name() { 222 | if f := v.FieldByIndex(f.indx); f.CanSet() { 223 | if v.CanAddr() { 224 | r.DecodeReflect(f.Addr()) 225 | } else { 226 | r.DecodeReflect(f) 227 | } 228 | } 229 | continue 230 | } 231 | } 232 | 233 | } 234 | 235 | } 236 | 237 | } 238 | -------------------------------------------------------------------------------- /reader_val.go: -------------------------------------------------------------------------------- 1 | // Copyright © SurrealDB Ltd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://wwr.deache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package cork 16 | 17 | import ( 18 | "encoding/binary" 19 | "reflect" 20 | "time" 21 | ) 22 | 23 | // DecodeInterface decodes any value from the Reader, with 24 | // whatever type is next in the stream. 25 | func (r *Reader) DecodeInterface(v *interface{}) { 26 | 27 | b := r.peekOne() 28 | 29 | switch { 30 | case b == cNil: 31 | r.readOne() 32 | *v = nil 33 | case isBool(b): 34 | var x bool 35 | r.DecodeBool(&x) 36 | *v = x 37 | case isTime(b): 38 | var x time.Time 39 | r.DecodeTime(&x) 40 | *v = x 41 | case isBin(b): 42 | var x []byte 43 | r.DecodeBytes(&x) 44 | *v = x 45 | case isStr(b): 46 | var x string 47 | r.DecodeString(&x) 48 | *v = x 49 | case isNum(b): 50 | var x int 51 | r.DecodeInt(&x) 52 | *v = x 53 | case isInt(b): 54 | var x int 55 | r.DecodeInt(&x) 56 | *v = x 57 | case isUint(b): 58 | var x uint 59 | r.DecodeUint(&x) 60 | *v = x 61 | case b == cFloat32: 62 | var x float32 63 | r.DecodeFloat32(&x) 64 | *v = x 65 | case b == cFloat64: 66 | var x float64 67 | r.DecodeFloat64(&x) 68 | *v = x 69 | case b == cComplex64: 70 | var x complex64 71 | r.DecodeComplex64(&x) 72 | *v = x 73 | case b == cComplex128: 74 | var x complex128 75 | r.DecodeComplex128(&x) 76 | *v = x 77 | 78 | // ------------------------- 79 | 80 | case isExt(b): 81 | *v = r.createExt() 82 | case isSlf(b): 83 | *v = r.createSlf() 84 | case isArr(b): 85 | *v = r.createArr() 86 | case isMap(b): 87 | *v = r.createMap() 88 | 89 | // ------------------------- 90 | 91 | default: 92 | panic(fail) 93 | 94 | } 95 | 96 | } 97 | 98 | func (r *Reader) createExt() (v Corker) { 99 | s := 0 100 | b := r.readOne() 101 | switch { 102 | case b >= cFixExt && b <= cFixExt+fixedExt: 103 | s = int(b - cFixExt) 104 | case b == cExt8: 105 | s = int(r.readOne()) 106 | case b == cExt16: 107 | s = int(binary.BigEndian.Uint16(r.readMany(2))) 108 | case b == cExt32: 109 | s = int(binary.BigEndian.Uint32(r.readMany(4))) 110 | case b == cExt64: 111 | s = int(binary.BigEndian.Uint64(r.readMany(8))) 112 | default: 113 | panic(fail) 114 | } 115 | e := r.readOne() 116 | d := r.readMany(s) 117 | v = reflect.New(registry[e]).Interface().(Corker) 118 | if err := v.UnmarshalCORK(d); err != nil { 119 | panic(err) 120 | } 121 | return 122 | } 123 | 124 | func (r *Reader) createSlf() (v Selfer) { 125 | if r.readOne() == cSlf { 126 | e := r.readOne() 127 | v = reflect.New(registry[e]).Interface().(Selfer) 128 | v.UnmarshalCORK(r) 129 | return 130 | } 131 | panic(fail) 132 | } 133 | 134 | func (r *Reader) createArr() (v interface{}) { 135 | if r.h != nil && r.h.ArrType != nil { 136 | switch a := r.h.ArrType.(type) { 137 | case []bool: 138 | var x []bool 139 | r.decodeArrBool(&x) 140 | return x 141 | case []int: 142 | var x []int 143 | r.decodeArrInt(&x) 144 | return x 145 | case []int8: 146 | var x []int8 147 | r.decodeArrInt8(&x) 148 | return x 149 | case []int16: 150 | var x []int16 151 | r.decodeArrInt16(&x) 152 | return x 153 | case []int32: 154 | var x []int32 155 | r.decodeArrInt32(&x) 156 | return x 157 | case []int64: 158 | var x []int64 159 | r.decodeArrInt64(&x) 160 | return x 161 | case []uint: 162 | var x []uint 163 | r.decodeArrUint(&x) 164 | return x 165 | case []uint16: 166 | var x []uint16 167 | r.decodeArrUint16(&x) 168 | return x 169 | case []uint32: 170 | var x []uint32 171 | r.decodeArrUint32(&x) 172 | return x 173 | case []uint64: 174 | var x []uint64 175 | r.decodeArrUint64(&x) 176 | return x 177 | case []string: 178 | var x []string 179 | r.decodeArrString(&x) 180 | return x 181 | case []float32: 182 | var x []float32 183 | r.decodeArrFloat32(&x) 184 | return x 185 | case []float64: 186 | var x []float64 187 | r.decodeArrFloat64(&x) 188 | return x 189 | case []complex64: 190 | var x []complex64 191 | r.decodeArrComplex64(&x) 192 | return x 193 | case []complex128: 194 | var x []complex128 195 | r.decodeArrComplex128(&x) 196 | return x 197 | case []time.Time: 198 | var x []time.Time 199 | r.decodeArrTime(&x) 200 | return x 201 | case reflect.Type: 202 | var x = reflect.MakeSlice(a, 0, 0) 203 | r.decodeArr(x) 204 | return x.Interface() 205 | } 206 | } 207 | var x []interface{} 208 | r.decodeArrAny(&x) 209 | return x 210 | } 211 | 212 | func (r *Reader) createMap() (v interface{}) { 213 | if r.h != nil && r.h.MapType != nil { 214 | switch m := r.h.MapType.(type) { 215 | default: 216 | case map[string]int: 217 | var x map[string]int 218 | r.decodeMapStringInt(&x) 219 | return x 220 | case map[string]uint: 221 | var x map[string]uint 222 | r.decodeMapStringUint(&x) 223 | return x 224 | case map[string]bool: 225 | var x map[string]bool 226 | r.decodeMapStringBool(&x) 227 | return x 228 | case map[string]string: 229 | var x map[string]string 230 | r.decodeMapStringString(&x) 231 | return x 232 | case map[int]interface{}: 233 | var x map[int]interface{} 234 | r.decodeMapIntAny(&x) 235 | return x 236 | case map[uint]interface{}: 237 | var x map[uint]interface{} 238 | r.decodeMapUintAny(&x) 239 | return x 240 | case map[string]interface{}: 241 | var x map[string]interface{} 242 | r.decodeMapStringAny(&x) 243 | return x 244 | case map[time.Time]interface{}: 245 | var x map[time.Time]interface{} 246 | r.decodeMapTimeAny(&x) 247 | return x 248 | case reflect.Type: 249 | var x = reflect.MakeMap(m) 250 | r.decodeMap(x) 251 | return x.Interface() 252 | } 253 | } 254 | var x map[interface{}]interface{} 255 | r.decodeMapAnyAny(&x) 256 | return x 257 | } 258 | -------------------------------------------------------------------------------- /reflect.go: -------------------------------------------------------------------------------- 1 | // Copyright © SurrealDB Ltd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package cork 16 | 17 | import ( 18 | "reflect" 19 | "time" 20 | ) 21 | 22 | var typeStr = reflect.TypeOf("") 23 | var typeBit = reflect.TypeOf([]uint8(nil)) 24 | var typeTime = reflect.TypeOf(time.Now()) 25 | var typeSelfer = reflect.TypeOf((*Selfer)(nil)).Elem() 26 | var typeCorker = reflect.TypeOf((*Corker)(nil)).Elem() 27 | -------------------------------------------------------------------------------- /registry.go: -------------------------------------------------------------------------------- 1 | // Copyright © SurrealDB Ltd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package cork 16 | 17 | import ( 18 | "reflect" 19 | ) 20 | 21 | var registry = make(map[byte]reflect.Type) 22 | 23 | // Register adds a Corker type to the registry, enabling the 24 | // object type to be encoded and decoded using the Corker methods. 25 | func Register(value interface{}) { 26 | 27 | switch val := value.(type) { 28 | case Corker: 29 | registry[val.ExtendCORK()] = reflect.TypeOf(val).Elem() 30 | case Selfer: 31 | registry[val.ExtendCORK()] = reflect.TypeOf(val).Elem() 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /sort.go: -------------------------------------------------------------------------------- 1 | // Copyright © SurrealDB Ltd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package cork 16 | 17 | import ( 18 | "bytes" 19 | "reflect" 20 | "sort" 21 | "time" 22 | ) 23 | 24 | type sortable struct { 25 | key []byte 26 | val interface{} 27 | ref reflect.Value 28 | } 29 | 30 | func sortMap(m reflect.Value) (a []*sortable) { 31 | for _, k := range m.MapKeys() { 32 | s := &sortable{ref: m.MapIndex(k)} 33 | NewEncoderBytes(&s.key).w.EncodeReflect(k) 34 | a = append(a, s) 35 | } 36 | sort.Slice(a, func(x, y int) bool { 37 | return bytes.Compare(a[x].key, a[y].key) < 0 38 | }) 39 | return 40 | } 41 | 42 | func sortMapStringInt(m map[string]int) (a []string) { 43 | for k := range m { 44 | a = append(a, k) 45 | } 46 | sort.Strings(a) 47 | return 48 | } 49 | 50 | func sortMapStringUint(m map[string]uint) (a []string) { 51 | for k := range m { 52 | a = append(a, k) 53 | } 54 | sort.Strings(a) 55 | return 56 | } 57 | 58 | func sortMapStringBool(m map[string]bool) (a []string) { 59 | for k := range m { 60 | a = append(a, k) 61 | } 62 | sort.Strings(a) 63 | return 64 | } 65 | 66 | func sortMapStringString(m map[string]string) (a []string) { 67 | for k := range m { 68 | a = append(a, k) 69 | } 70 | sort.Strings(a) 71 | return 72 | } 73 | 74 | func sortMapIntAny(m map[int]interface{}) (a []int) { 75 | for k := range m { 76 | a = append(a, k) 77 | } 78 | sort.Ints(a) 79 | return 80 | } 81 | 82 | func sortMapUintAny(m map[uint]interface{}) (a []uint) { 83 | for k := range m { 84 | a = append(a, k) 85 | } 86 | sort.Slice(a, func(x, y int) bool { 87 | return a[x] < a[y] 88 | }) 89 | return 90 | } 91 | 92 | func sortMapStringAny(m map[string]interface{}) (a []string) { 93 | for k := range m { 94 | a = append(a, k) 95 | } 96 | sort.Strings(a) 97 | return 98 | } 99 | 100 | func sortMapTimeAny(m map[time.Time]interface{}) (a []time.Time) { 101 | for k := range m { 102 | a = append(a, k) 103 | } 104 | sort.Slice(a, func(x, y int) bool { 105 | return a[x].UnixNano() < a[y].UnixNano() 106 | }) 107 | return 108 | } 109 | 110 | func sortMapAnyAny(m map[interface{}]interface{}) (a []*sortable) { 111 | for k, v := range m { 112 | s := &sortable{val: v} 113 | NewEncoderBytes(&s.key).w.EncodeAny(k) 114 | a = append(a, s) 115 | } 116 | sort.Slice(a, func(x, y int) bool { 117 | return bytes.Compare(a[x].key, a[y].key) < 0 118 | }) 119 | return 120 | } 121 | -------------------------------------------------------------------------------- /util.go: -------------------------------------------------------------------------------- 1 | // Copyright © SurrealDB Ltd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package cork 16 | 17 | func isBool(b byte) bool { 18 | return b == cTrue || b == cFalse 19 | } 20 | 21 | func isNum(b byte) bool { 22 | return b >= cFixInt && b <= cFixInt+fixedInt 23 | } 24 | 25 | func isBin(b byte) bool { 26 | return b == cBin8 || b == cBin16 || b == cBin32 || b == cBin64 || (b >= cFixBin && b <= cFixBin+fixedBin) 27 | } 28 | 29 | func isStr(b byte) bool { 30 | return b == cStr8 || b == cStr16 || b == cStr32 || b == cStr64 || (b >= cFixStr && b <= cFixStr+fixedStr) 31 | } 32 | 33 | func isExt(b byte) bool { 34 | return b == cExt8 || b == cExt16 || b == cExt32 || b == cExt64 || (b >= cFixExt && b <= cFixExt+fixedExt) 35 | } 36 | 37 | func isInt(b byte) bool { 38 | return b == cInt8 || b == cInt16 || b == cInt32 || b == cInt64 || isNum(b) 39 | } 40 | 41 | func isUint(b byte) bool { 42 | return b == cUint8 || b == cUint16 || b == cUint32 || b == cUint64 || isNum(b) 43 | } 44 | 45 | func isTime(b byte) bool { 46 | return b == cTime 47 | } 48 | 49 | func isArr(b byte) bool { 50 | return b == cArr || (b >= cFixArr && b <= cFixArr+fixedArr) 51 | } 52 | 53 | func isMap(b byte) bool { 54 | return b == cMap || (b >= cFixMap && b <= cFixMap+fixedMap) 55 | } 56 | 57 | func isSlf(b byte) bool { 58 | return b == cSlf 59 | } 60 | -------------------------------------------------------------------------------- /writer.go: -------------------------------------------------------------------------------- 1 | // Copyright © SurrealDB Ltd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package cork 16 | 17 | import ( 18 | "math" 19 | "time" 20 | 21 | "github.com/surrealdb/bump" 22 | ) 23 | 24 | // Writer is used when self-encoding a cork.Selfer item into binary form. 25 | type Writer struct { 26 | h *Handle 27 | w *bump.Writer 28 | } 29 | 30 | func newWriter() *Writer { 31 | return &Writer{ 32 | w: bump.NewWriter(nil), 33 | } 34 | } 35 | 36 | func (w *Writer) writeOne(v byte) { 37 | if err := w.w.WriteByte(v); err != nil { 38 | panic(err) 39 | } 40 | } 41 | 42 | func (w *Writer) writeMany(v []byte) { 43 | if err := w.w.WriteBytes(v); err != nil { 44 | panic(err) 45 | } 46 | } 47 | 48 | func (w *Writer) writeText(v string) { 49 | if err := w.w.WriteString(v); err != nil { 50 | panic(err) 51 | } 52 | } 53 | 54 | // --------------------------------------------------------------------------- 55 | 56 | func (w *Writer) writeLen(v uint) { 57 | switch { 58 | case v >= 0 && v <= fixedInt: 59 | w.writeOne(byte(v)) 60 | case v <= math.MaxUint8: 61 | w.writeOne(cUint8) 62 | w.writeOne(byte(v)) 63 | case v <= math.MaxUint16: 64 | w.writeOne(cUint16) 65 | w.writeOne(byte(v >> 8)) 66 | w.writeOne(byte(v)) 67 | case v <= math.MaxUint32: 68 | w.writeOne(cUint32) 69 | w.writeOne(byte(v >> 24)) 70 | w.writeOne(byte(v >> 16)) 71 | w.writeOne(byte(v >> 8)) 72 | w.writeOne(byte(v)) 73 | case v <= math.MaxUint64: 74 | w.writeOne(cUint64) 75 | w.writeOne(byte(v >> 56)) 76 | w.writeOne(byte(v >> 48)) 77 | w.writeOne(byte(v >> 40)) 78 | w.writeOne(byte(v >> 32)) 79 | w.writeOne(byte(v >> 24)) 80 | w.writeOne(byte(v >> 16)) 81 | w.writeOne(byte(v >> 8)) 82 | w.writeOne(byte(v)) 83 | } 84 | } 85 | 86 | func (w *Writer) writeLen8(val uint8) { 87 | w.writeOne(byte(val)) 88 | } 89 | 90 | func (w *Writer) writeLen16(val uint16) { 91 | w.writeOne(byte(val >> 8)) 92 | w.writeOne(byte(val)) 93 | } 94 | 95 | func (w *Writer) writeLen32(val uint32) { 96 | w.writeOne(byte(val >> 24)) 97 | w.writeOne(byte(val >> 16)) 98 | w.writeOne(byte(val >> 8)) 99 | w.writeOne(byte(val)) 100 | } 101 | 102 | func (w *Writer) writeLen64(val uint64) { 103 | w.writeOne(byte(val >> 56)) 104 | w.writeOne(byte(val >> 48)) 105 | w.writeOne(byte(val >> 40)) 106 | w.writeOne(byte(val >> 32)) 107 | w.writeOne(byte(val >> 24)) 108 | w.writeOne(byte(val >> 16)) 109 | w.writeOne(byte(val >> 8)) 110 | w.writeOne(byte(val)) 111 | } 112 | 113 | // --------------------------------------------------------------------------- 114 | 115 | // EncodeBool writes a nil value to the Writer. 116 | func (w *Writer) EncodeNil() { 117 | w.writeOne(cNil) 118 | } 119 | 120 | // EncodeBool encodes a boolean value to the Writer. 121 | func (w *Writer) EncodeBool(v bool) { 122 | if v { 123 | w.writeOne(cTrue) 124 | } else { 125 | w.writeOne(cFalse) 126 | } 127 | } 128 | 129 | // EncodeByte encodes a byte value to the Writer. 130 | func (w *Writer) EncodeByte(v byte) { 131 | w.writeOne(v) 132 | } 133 | 134 | // EncodeBytes encodes a byte slice value to the Writer. 135 | func (w *Writer) EncodeBytes(v []byte) { 136 | sze := len(v) 137 | switch { 138 | case sze <= fixedBin: 139 | w.writeOne(cFixBin + byte(sze)) 140 | case sze <= math.MaxUint8: 141 | w.writeOne(cBin8) 142 | w.writeLen8(uint8(sze)) 143 | case sze <= math.MaxUint16: 144 | w.writeOne(cBin16) 145 | w.writeLen16(uint16(sze)) 146 | case sze <= math.MaxUint32: 147 | w.writeOne(cBin32) 148 | w.writeLen32(uint32(sze)) 149 | case sze <= math.MaxInt64: 150 | w.writeOne(cBin64) 151 | w.writeLen64(uint64(sze)) 152 | } 153 | w.writeMany(v) 154 | } 155 | 156 | // EncodeString encodes a string value to the Writer. 157 | func (w *Writer) EncodeString(v string) { 158 | sze := len(v) 159 | switch { 160 | case sze <= fixedStr: 161 | w.writeOne(cFixStr + byte(sze)) 162 | case sze <= math.MaxUint8: 163 | w.writeOne(cStr8) 164 | w.writeLen8(uint8(sze)) 165 | case sze <= math.MaxUint16: 166 | w.writeOne(cStr16) 167 | w.writeLen16(uint16(sze)) 168 | case sze <= math.MaxUint32: 169 | w.writeOne(cStr32) 170 | w.writeLen32(uint32(sze)) 171 | case sze <= math.MaxInt64: 172 | w.writeOne(cStr64) 173 | w.writeLen64(uint64(sze)) 174 | } 175 | w.writeText(v) 176 | } 177 | 178 | // --------------------------------------------------------------------------- 179 | 180 | // EncodeInt encodes an int value to the Writer. 181 | func (w *Writer) EncodeInt(v int) { 182 | switch { 183 | case v >= 0 && v <= fixedInt: 184 | w.writeOne(byte(v)) 185 | case v >= math.MinInt8 && v <= math.MaxInt8: 186 | w.writeOne(cInt8) 187 | w.writeOne(byte(v)) 188 | case v >= math.MinInt16 && v <= math.MaxInt16: 189 | w.writeOne(cInt16) 190 | w.writeOne(byte(v >> 8)) 191 | w.writeOne(byte(v)) 192 | case v >= math.MinInt32 && v <= math.MaxInt32: 193 | w.writeOne(cInt32) 194 | w.writeOne(byte(v >> 24)) 195 | w.writeOne(byte(v >> 16)) 196 | w.writeOne(byte(v >> 8)) 197 | w.writeOne(byte(v)) 198 | case v >= math.MinInt64 && v <= math.MaxInt64: 199 | w.writeOne(cInt64) 200 | w.writeOne(byte(v >> 56)) 201 | w.writeOne(byte(v >> 48)) 202 | w.writeOne(byte(v >> 40)) 203 | w.writeOne(byte(v >> 32)) 204 | w.writeOne(byte(v >> 24)) 205 | w.writeOne(byte(v >> 16)) 206 | w.writeOne(byte(v >> 8)) 207 | w.writeOne(byte(v)) 208 | } 209 | } 210 | 211 | // EncodeInt8 encodes an int8 value to the Writer. 212 | func (w *Writer) EncodeInt8(v int8) { 213 | w.EncodeInt(int(v)) 214 | } 215 | 216 | // EncodeInt16 encodes an int16 value to the Writer. 217 | func (w *Writer) EncodeInt16(v int16) { 218 | w.EncodeInt(int(v)) 219 | } 220 | 221 | // EncodeInt32 encodes an int32 value to the Writer. 222 | func (w *Writer) EncodeInt32(v int32) { 223 | w.EncodeInt(int(v)) 224 | } 225 | 226 | // EncodeInt64 encodes an int64 value to the Writer. 227 | func (w *Writer) EncodeInt64(v int64) { 228 | w.EncodeInt(int(v)) 229 | } 230 | 231 | // --------------------------------------------------------------------------- 232 | 233 | // EncodeUint encodes a uint value to the Writer. 234 | func (w *Writer) EncodeUint(v uint) { 235 | switch { 236 | case v >= 0 && v <= fixedInt: 237 | w.writeOne(byte(v)) 238 | case v <= math.MaxUint8: 239 | w.writeOne(cUint8) 240 | w.writeOne(byte(v)) 241 | case v <= math.MaxUint16: 242 | w.writeOne(cUint16) 243 | w.writeOne(byte(v >> 8)) 244 | w.writeOne(byte(v)) 245 | case v <= math.MaxUint32: 246 | w.writeOne(cUint32) 247 | w.writeOne(byte(v >> 24)) 248 | w.writeOne(byte(v >> 16)) 249 | w.writeOne(byte(v >> 8)) 250 | w.writeOne(byte(v)) 251 | case v <= math.MaxUint64: 252 | w.writeOne(cUint64) 253 | w.writeOne(byte(v >> 56)) 254 | w.writeOne(byte(v >> 48)) 255 | w.writeOne(byte(v >> 40)) 256 | w.writeOne(byte(v >> 32)) 257 | w.writeOne(byte(v >> 24)) 258 | w.writeOne(byte(v >> 16)) 259 | w.writeOne(byte(v >> 8)) 260 | w.writeOne(byte(v)) 261 | } 262 | } 263 | 264 | // EncodeUint8 encodes a uint8 value to the Writer. 265 | func (w *Writer) EncodeUint8(v uint8) { 266 | w.EncodeUint(uint(v)) 267 | } 268 | 269 | // EncodeUint16 encodes a uint16 value to the Writer. 270 | func (w *Writer) EncodeUint16(v uint16) { 271 | w.EncodeUint(uint(v)) 272 | } 273 | 274 | // EncodeUint32 encodes a uint32 value to the Writer. 275 | func (w *Writer) EncodeUint32(v uint32) { 276 | w.EncodeUint(uint(v)) 277 | } 278 | 279 | // EncodeUint64 encodes a uint64 value to the Writer. 280 | func (w *Writer) EncodeUint64(v uint64) { 281 | w.EncodeUint(uint(v)) 282 | } 283 | 284 | // --------------------------------------------------------------------------- 285 | 286 | // EncodeFloat32 encodes a float32 value to the Writer. 287 | func (w *Writer) EncodeFloat32(v float32) { 288 | tmp := math.Float32bits(v) 289 | w.writeOne(cFloat32) 290 | w.writeOne(byte(tmp >> 24)) 291 | w.writeOne(byte(tmp >> 16)) 292 | w.writeOne(byte(tmp >> 8)) 293 | w.writeOne(byte(tmp)) 294 | } 295 | 296 | // EncodeFloat64 encodes a float64 value to the Writer. 297 | func (w *Writer) EncodeFloat64(v float64) { 298 | tmp := math.Float64bits(v) 299 | w.writeOne(cFloat64) 300 | w.writeOne(byte(tmp >> 56)) 301 | w.writeOne(byte(tmp >> 48)) 302 | w.writeOne(byte(tmp >> 40)) 303 | w.writeOne(byte(tmp >> 32)) 304 | w.writeOne(byte(tmp >> 24)) 305 | w.writeOne(byte(tmp >> 16)) 306 | w.writeOne(byte(tmp >> 8)) 307 | w.writeOne(byte(tmp)) 308 | } 309 | 310 | // --------------------------------------------------------------------------- 311 | 312 | // EncodeComplex64 encodes a complex64 value to the Writer. 313 | func (w *Writer) EncodeComplex64(v complex64) { 314 | one := math.Float32bits(real(v)) 315 | two := math.Float32bits(imag(v)) 316 | w.writeOne(cComplex64) 317 | w.writeOne(byte(one >> 24)) 318 | w.writeOne(byte(one >> 16)) 319 | w.writeOne(byte(one >> 8)) 320 | w.writeOne(byte(one)) 321 | w.writeOne(byte(two >> 24)) 322 | w.writeOne(byte(two >> 16)) 323 | w.writeOne(byte(two >> 8)) 324 | w.writeOne(byte(two)) 325 | } 326 | 327 | // EncodeComplex128 encodes a complex128 value to the Writer. 328 | func (w *Writer) EncodeComplex128(v complex128) { 329 | one := math.Float64bits(real(v)) 330 | two := math.Float64bits(imag(v)) 331 | w.writeOne(cComplex128) 332 | w.writeOne(byte(one >> 56)) 333 | w.writeOne(byte(one >> 48)) 334 | w.writeOne(byte(one >> 40)) 335 | w.writeOne(byte(one >> 32)) 336 | w.writeOne(byte(one >> 24)) 337 | w.writeOne(byte(one >> 16)) 338 | w.writeOne(byte(one >> 8)) 339 | w.writeOne(byte(one)) 340 | w.writeOne(byte(two >> 56)) 341 | w.writeOne(byte(two >> 48)) 342 | w.writeOne(byte(two >> 40)) 343 | w.writeOne(byte(two >> 32)) 344 | w.writeOne(byte(two >> 24)) 345 | w.writeOne(byte(two >> 16)) 346 | w.writeOne(byte(two >> 8)) 347 | w.writeOne(byte(two)) 348 | } 349 | 350 | // --------------------------------------------------------------------------- 351 | 352 | // EncodeInt encodes a time.Time value to the Writer. 353 | func (w *Writer) EncodeTime(v time.Time) { 354 | tmp := uint64(v.UTC().UnixNano()) 355 | w.writeOne(cTime) 356 | w.writeOne(byte(tmp >> 56)) 357 | w.writeOne(byte(tmp >> 48)) 358 | w.writeOne(byte(tmp >> 40)) 359 | w.writeOne(byte(tmp >> 32)) 360 | w.writeOne(byte(tmp >> 24)) 361 | w.writeOne(byte(tmp >> 16)) 362 | w.writeOne(byte(tmp >> 8)) 363 | w.writeOne(byte(tmp)) 364 | } 365 | 366 | // --------------------------------------------------------------------------- 367 | 368 | // EncodeArr encodes an array to the Writer. 369 | func (w *Writer) EncodeArr(v interface{}) { 370 | switch a := v.(type) { 371 | case []bool: 372 | w.encodeArrBool(a) 373 | case []int: 374 | w.encodeArrInt(a) 375 | case []int8: 376 | w.encodeArrInt8(a) 377 | case []int16: 378 | w.encodeArrInt16(a) 379 | case []int32: 380 | w.encodeArrInt32(a) 381 | case []int64: 382 | w.encodeArrInt64(a) 383 | case []uint: 384 | w.encodeArrUint(a) 385 | case []uint8: 386 | w.encodeArrUint8(a) 387 | case []uint16: 388 | w.encodeArrUint16(a) 389 | case []uint32: 390 | w.encodeArrUint32(a) 391 | case []uint64: 392 | w.encodeArrUint64(a) 393 | case []string: 394 | w.encodeArrString(a) 395 | case []float32: 396 | w.encodeArrFloat32(a) 397 | case []float64: 398 | w.encodeArrFloat64(a) 399 | case []complex64: 400 | w.encodeArrComplex64(a) 401 | case []complex128: 402 | w.encodeArrComplex128(a) 403 | case []time.Time: 404 | w.encodeArrTime(a) 405 | case []interface{}: 406 | w.encodeArrAny(a) 407 | default: 408 | w.EncodeAny(v) 409 | } 410 | } 411 | 412 | func (w *Writer) encodeArrLen(v int) { 413 | switch { 414 | case v >= 0 && v <= fixedArr: 415 | w.writeOne(cFixArr + byte(v)) 416 | default: 417 | w.writeOne(cArr) 418 | w.writeLen(uint(v)) 419 | } 420 | } 421 | 422 | // EncodeMap encodes a map to the Writer. 423 | func (w *Writer) EncodeMap(v interface{}) { 424 | switch m := v.(type) { 425 | case map[string]int: 426 | w.encodeMapStringInt(m) 427 | case map[string]uint: 428 | w.encodeMapStringUint(m) 429 | case map[string]bool: 430 | w.encodeMapStringBool(m) 431 | case map[string]string: 432 | w.encodeMapStringString(m) 433 | case map[int]interface{}: 434 | w.encodeMapIntAny(m) 435 | case map[uint]interface{}: 436 | w.encodeMapUintAny(m) 437 | case map[string]interface{}: 438 | w.encodeMapStringAny(m) 439 | case map[time.Time]interface{}: 440 | w.encodeMapTimeAny(m) 441 | case map[interface{}]interface{}: 442 | w.encodeMapAnyAny(m) 443 | default: 444 | w.EncodeAny(v) 445 | } 446 | } 447 | 448 | func (w *Writer) encodeMapLen(v int) { 449 | switch { 450 | case v >= 0 && v <= fixedMap: 451 | w.writeOne(cFixMap + byte(v)) 452 | default: 453 | w.writeOne(cMap) 454 | w.writeLen(uint(v)) 455 | } 456 | } 457 | -------------------------------------------------------------------------------- /writer_any.go: -------------------------------------------------------------------------------- 1 | // Copyright © SurrealDB Ltd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package cork 16 | 17 | import ( 18 | "encoding" 19 | "reflect" 20 | "time" 21 | ) 22 | 23 | func (w *Writer) EncodeAny(v interface{}) { 24 | 25 | switch v := v.(type) { 26 | 27 | case Selfer: 28 | w.EncodeSelfer(v) 29 | case Corker: 30 | w.EncodeCorker(v) 31 | 32 | // ------------------------- 33 | 34 | case nil: 35 | w.EncodeNil() 36 | case bool: 37 | w.EncodeBool(v) 38 | case byte: 39 | w.EncodeByte(v) 40 | case []byte: 41 | w.EncodeBytes(v) 42 | case string: 43 | w.EncodeString(v) 44 | case int: 45 | w.EncodeInt(v) 46 | case int8: 47 | w.EncodeInt(int(v)) 48 | case int16: 49 | w.EncodeInt(int(v)) 50 | case int32: 51 | w.EncodeInt(int(v)) 52 | case int64: 53 | w.EncodeInt(int(v)) 54 | case uint: 55 | w.EncodeUint(v) 56 | case uint16: 57 | w.EncodeUint(uint(v)) 58 | case uint32: 59 | w.EncodeUint(uint(v)) 60 | case uint64: 61 | w.EncodeUint(uint(v)) 62 | case float32: 63 | w.EncodeFloat32(v) 64 | case float64: 65 | w.EncodeFloat64(v) 66 | case complex64: 67 | w.EncodeComplex64(v) 68 | case complex128: 69 | w.EncodeComplex128(v) 70 | case time.Time: 71 | w.EncodeTime(v) 72 | 73 | // ------------------------- 74 | 75 | case []bool: 76 | w.encodeArrBool(v) 77 | case []int: 78 | w.encodeArrInt(v) 79 | case []int8: 80 | w.encodeArrInt8(v) 81 | case []int16: 82 | w.encodeArrInt16(v) 83 | case []int32: 84 | w.encodeArrInt32(v) 85 | case []int64: 86 | w.encodeArrInt64(v) 87 | case []uint: 88 | w.encodeArrUint(v) 89 | case []uint16: 90 | w.encodeArrUint16(v) 91 | case []uint32: 92 | w.encodeArrUint32(v) 93 | case []uint64: 94 | w.encodeArrUint64(v) 95 | case []string: 96 | w.encodeArrString(v) 97 | case []float32: 98 | w.encodeArrFloat32(v) 99 | case []float64: 100 | w.encodeArrFloat64(v) 101 | case []complex64: 102 | w.encodeArrComplex64(v) 103 | case []complex128: 104 | w.encodeArrComplex128(v) 105 | case []time.Time: 106 | w.encodeArrTime(v) 107 | case []interface{}: 108 | w.encodeArrAny(v) 109 | 110 | // ------------------------- 111 | 112 | case map[string]int: 113 | w.encodeMapStringInt(v) 114 | case map[string]uint: 115 | w.encodeMapStringUint(v) 116 | case map[string]bool: 117 | w.encodeMapStringBool(v) 118 | case map[string]string: 119 | w.encodeMapStringString(v) 120 | case map[int]interface{}: 121 | w.encodeMapIntAny(v) 122 | case map[uint]interface{}: 123 | w.encodeMapUintAny(v) 124 | case map[string]interface{}: 125 | w.encodeMapStringAny(v) 126 | case map[time.Time]interface{}: 127 | w.encodeMapTimeAny(v) 128 | case map[interface{}]interface{}: 129 | w.encodeMapAnyAny(v) 130 | 131 | // ------------------------- 132 | 133 | case encoding.BinaryMarshaler: 134 | enc, err := v.MarshalBinary() 135 | if err != nil { 136 | panic(err) 137 | } 138 | w.EncodeBytes(enc) 139 | 140 | case encoding.TextMarshaler: 141 | enc, err := v.MarshalText() 142 | if err != nil { 143 | panic(err) 144 | } 145 | w.EncodeBytes(enc) 146 | 147 | default: 148 | w.EncodeReflect(reflect.ValueOf(v)) 149 | 150 | } 151 | 152 | } 153 | -------------------------------------------------------------------------------- /writer_arr.go: -------------------------------------------------------------------------------- 1 | // Copyright © SurrealDB Ltd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package cork 16 | 17 | import ( 18 | "reflect" 19 | "time" 20 | ) 21 | 22 | func (w *Writer) encodeArr(a reflect.Value) { 23 | w.encodeArrLen(a.Len()) 24 | for i := 0; i < a.Len(); i++ { 25 | w.EncodeReflect(a.Index(i)) 26 | } 27 | } 28 | 29 | func (w *Writer) encodeArrBool(a []bool) { 30 | w.encodeArrLen(len(a)) 31 | for _, v := range a { 32 | w.EncodeBool(v) 33 | } 34 | } 35 | 36 | func (w *Writer) encodeArrInt(a []int) { 37 | w.encodeArrLen(len(a)) 38 | for _, v := range a { 39 | w.EncodeInt(v) 40 | } 41 | } 42 | 43 | func (w *Writer) encodeArrInt8(a []int8) { 44 | w.encodeArrLen(len(a)) 45 | for _, v := range a { 46 | w.EncodeInt(int(v)) 47 | } 48 | } 49 | 50 | func (w *Writer) encodeArrInt16(a []int16) { 51 | w.encodeArrLen(len(a)) 52 | for _, v := range a { 53 | w.EncodeInt(int(v)) 54 | } 55 | } 56 | 57 | func (w *Writer) encodeArrInt32(a []int32) { 58 | w.encodeArrLen(len(a)) 59 | for _, v := range a { 60 | w.EncodeInt(int(v)) 61 | } 62 | } 63 | 64 | func (w *Writer) encodeArrInt64(a []int64) { 65 | w.encodeArrLen(len(a)) 66 | for _, v := range a { 67 | w.EncodeInt(int(v)) 68 | } 69 | } 70 | 71 | func (w *Writer) encodeArrUint(a []uint) { 72 | w.encodeArrLen(len(a)) 73 | for _, v := range a { 74 | w.EncodeUint(v) 75 | } 76 | } 77 | 78 | func (w *Writer) encodeArrUint8(a []uint8) { 79 | w.encodeArrLen(len(a)) 80 | for _, v := range a { 81 | w.EncodeUint(uint(v)) 82 | } 83 | } 84 | 85 | func (w *Writer) encodeArrUint16(a []uint16) { 86 | w.encodeArrLen(len(a)) 87 | for _, v := range a { 88 | w.EncodeUint(uint(v)) 89 | } 90 | } 91 | 92 | func (w *Writer) encodeArrUint32(a []uint32) { 93 | w.encodeArrLen(len(a)) 94 | for _, v := range a { 95 | w.EncodeUint(uint(v)) 96 | } 97 | } 98 | 99 | func (w *Writer) encodeArrUint64(a []uint64) { 100 | w.encodeArrLen(len(a)) 101 | for _, v := range a { 102 | w.EncodeUint(uint(v)) 103 | } 104 | } 105 | 106 | func (w *Writer) encodeArrString(a []string) { 107 | w.encodeArrLen(len(a)) 108 | for _, v := range a { 109 | w.EncodeString(v) 110 | } 111 | } 112 | 113 | func (w *Writer) encodeArrFloat32(a []float32) { 114 | w.encodeArrLen(len(a)) 115 | for _, v := range a { 116 | w.EncodeFloat32(v) 117 | } 118 | } 119 | 120 | func (w *Writer) encodeArrFloat64(a []float64) { 121 | w.encodeArrLen(len(a)) 122 | for _, v := range a { 123 | w.EncodeFloat64(v) 124 | } 125 | } 126 | 127 | func (w *Writer) encodeArrComplex64(a []complex64) { 128 | w.encodeArrLen(len(a)) 129 | for _, v := range a { 130 | w.EncodeComplex64(v) 131 | } 132 | } 133 | 134 | func (w *Writer) encodeArrComplex128(a []complex128) { 135 | w.encodeArrLen(len(a)) 136 | for _, v := range a { 137 | w.EncodeComplex128(v) 138 | } 139 | } 140 | 141 | func (w *Writer) encodeArrTime(a []time.Time) { 142 | w.encodeArrLen(len(a)) 143 | for _, v := range a { 144 | w.EncodeTime(v) 145 | } 146 | } 147 | 148 | func (w *Writer) encodeArrAny(a []interface{}) { 149 | w.encodeArrLen(len(a)) 150 | for _, v := range a { 151 | w.EncodeAny(v) 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /writer_ext.go: -------------------------------------------------------------------------------- 1 | // Copyright © SurrealDB Ltd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package cork 16 | 17 | import ( 18 | "math" 19 | ) 20 | 21 | // EncodeSelfer encodes a cork.Selfer value to the Writer. 22 | func (w *Writer) EncodeSelfer(v Selfer) { 23 | w.writeOne(cSlf) 24 | w.writeOne(v.ExtendCORK()) 25 | v.MarshalCORK(w) 26 | } 27 | 28 | // EncodeCorker encodes a cork.Corker value to the Writer. 29 | func (w *Writer) EncodeCorker(v Corker) { 30 | enc, err := v.MarshalCORK() 31 | if err != nil { 32 | panic(err) 33 | } 34 | sze := len(enc) 35 | switch { 36 | case sze <= fixedExt: 37 | w.writeOne(cFixExt + byte(sze)) 38 | case sze <= math.MaxUint8: 39 | w.writeOne(cExt8) 40 | w.writeLen8(uint8(sze)) 41 | case sze <= math.MaxUint16: 42 | w.writeOne(cExt16) 43 | w.writeLen16(uint16(sze)) 44 | case sze <= math.MaxUint32: 45 | w.writeOne(cExt32) 46 | w.writeLen32(uint32(sze)) 47 | case sze <= math.MaxInt64: 48 | w.writeOne(cExt64) 49 | w.writeLen64(uint64(sze)) 50 | } 51 | w.writeOne(v.ExtendCORK()) 52 | w.writeMany(enc) 53 | } 54 | -------------------------------------------------------------------------------- /writer_map.go: -------------------------------------------------------------------------------- 1 | // Copyright © SurrealDB Ltd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package cork 16 | 17 | import ( 18 | "reflect" 19 | "time" 20 | ) 21 | 22 | func (w *Writer) encodeMap(m reflect.Value) { 23 | w.encodeMapLen(m.Len()) 24 | if w.h != nil && w.h.SortMaps { 25 | for _, v := range sortMap(m) { 26 | w.writeMany(v.key) 27 | w.EncodeReflect(v.ref) 28 | } 29 | } else { 30 | for _, k := range m.MapKeys() { 31 | w.EncodeReflect(k) 32 | w.EncodeReflect(m.MapIndex(k)) 33 | } 34 | } 35 | } 36 | 37 | func (w *Writer) encodeMapStringInt(m map[string]int) { 38 | w.encodeMapLen(len(m)) 39 | if w.h != nil && w.h.SortMaps { 40 | for _, v := range sortMapStringInt(m) { 41 | w.EncodeString(v) 42 | w.EncodeInt(m[v]) 43 | } 44 | } else { 45 | for k, v := range m { 46 | w.EncodeString(k) 47 | w.EncodeInt(v) 48 | } 49 | } 50 | } 51 | 52 | func (w *Writer) encodeMapStringUint(m map[string]uint) { 53 | w.encodeMapLen(len(m)) 54 | if w.h != nil && w.h.SortMaps { 55 | for _, v := range sortMapStringUint(m) { 56 | w.EncodeString(v) 57 | w.EncodeUint(m[v]) 58 | } 59 | } else { 60 | for k, v := range m { 61 | w.EncodeString(k) 62 | w.EncodeUint(v) 63 | } 64 | } 65 | } 66 | 67 | func (w *Writer) encodeMapStringBool(m map[string]bool) { 68 | w.encodeMapLen(len(m)) 69 | if w.h != nil && w.h.SortMaps { 70 | for _, v := range sortMapStringBool(m) { 71 | w.EncodeString(v) 72 | w.EncodeBool(m[v]) 73 | } 74 | } else { 75 | for k, v := range m { 76 | w.EncodeString(k) 77 | w.EncodeBool(v) 78 | } 79 | } 80 | } 81 | 82 | func (w *Writer) encodeMapStringString(m map[string]string) { 83 | w.encodeMapLen(len(m)) 84 | if w.h != nil && w.h.SortMaps { 85 | for _, v := range sortMapStringString(m) { 86 | w.EncodeString(v) 87 | w.EncodeString(m[v]) 88 | } 89 | } else { 90 | for k, v := range m { 91 | w.EncodeString(k) 92 | w.EncodeString(v) 93 | } 94 | } 95 | } 96 | 97 | func (w *Writer) encodeMapIntAny(m map[int]interface{}) { 98 | w.encodeMapLen(len(m)) 99 | if w.h != nil && w.h.SortMaps { 100 | for _, v := range sortMapIntAny(m) { 101 | w.EncodeInt(v) 102 | w.EncodeAny(m[v]) 103 | } 104 | } else { 105 | for k, v := range m { 106 | w.EncodeInt(k) 107 | w.EncodeAny(v) 108 | } 109 | } 110 | } 111 | 112 | func (w *Writer) encodeMapUintAny(m map[uint]interface{}) { 113 | w.encodeMapLen(len(m)) 114 | if w.h != nil && w.h.SortMaps { 115 | for _, v := range sortMapUintAny(m) { 116 | w.EncodeUint(v) 117 | w.EncodeAny(m[v]) 118 | } 119 | } else { 120 | for k, v := range m { 121 | w.EncodeUint(k) 122 | w.EncodeAny(v) 123 | } 124 | } 125 | } 126 | 127 | func (w *Writer) encodeMapStringAny(m map[string]interface{}) { 128 | w.encodeMapLen(len(m)) 129 | if w.h != nil && w.h.SortMaps { 130 | for _, v := range sortMapStringAny(m) { 131 | w.EncodeString(v) 132 | w.EncodeAny(m[v]) 133 | } 134 | } else { 135 | for k, v := range m { 136 | w.EncodeString(k) 137 | w.EncodeAny(v) 138 | } 139 | } 140 | } 141 | 142 | func (w *Writer) encodeMapTimeAny(m map[time.Time]interface{}) { 143 | w.encodeMapLen(len(m)) 144 | if w.h != nil && w.h.SortMaps { 145 | for _, v := range sortMapTimeAny(m) { 146 | w.EncodeTime(v) 147 | w.EncodeAny(m[v]) 148 | } 149 | } else { 150 | for k, v := range m { 151 | w.EncodeTime(k) 152 | w.EncodeAny(v) 153 | } 154 | } 155 | } 156 | 157 | func (w *Writer) encodeMapAnyAny(m map[interface{}]interface{}) { 158 | w.encodeMapLen(len(m)) 159 | if w.h != nil && w.h.SortMaps { 160 | for _, v := range sortMapAnyAny(m) { 161 | w.writeMany(v.key) 162 | w.EncodeAny(v.val) 163 | } 164 | } else { 165 | for k, v := range m { 166 | w.EncodeAny(k) 167 | w.EncodeAny(v) 168 | } 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /writer_ref.go: -------------------------------------------------------------------------------- 1 | // Copyright © SurrealDB Ltd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package cork 16 | 17 | import ( 18 | "reflect" 19 | "time" 20 | ) 21 | 22 | // EncodeReflect encodes a reflect.Value value to the Writer. 23 | func (w *Writer) EncodeReflect(v reflect.Value) { 24 | 25 | // If the element is a function or a 26 | // channel, then we can ignore these 27 | // types as these are not able to be 28 | // encoded. In addition, if the value 29 | // is a nil pointer or interface then 30 | // we can encode nil immediately. 31 | 32 | k := v.Kind() 33 | 34 | switch k { 35 | case reflect.Func, reflect.Chan: 36 | w.EncodeNil() 37 | return 38 | case reflect.Ptr, reflect.Interface: 39 | if v.IsNil() { 40 | w.EncodeNil() 41 | return 42 | } 43 | } 44 | 45 | // Next let's check to see if the type 46 | // implements either the Selfer or Corker 47 | // interfaces, and if it does then encode 48 | // it directly. Caching the interface 49 | // detection speeds up the encoding. 50 | 51 | t := v.Type() 52 | 53 | if c.Selfable(t) { 54 | w.EncodeSelfer(v.Interface().(Selfer)) 55 | return 56 | } 57 | 58 | if c.Corkable(t) { 59 | w.EncodeCorker(v.Interface().(Corker)) 60 | return 61 | } 62 | 63 | // It wasn't a self describing interface 64 | // so let's now see if it is a string or 65 | // a byte slice, and if it is, then 66 | // encode it immediately. 67 | 68 | switch t { 69 | 70 | case typeStr: 71 | w.EncodeString(v.String()) 72 | return 73 | 74 | case typeBit: 75 | w.EncodeBytes(v.Bytes()) 76 | return 77 | 78 | case typeTime: 79 | w.EncodeTime(v.Interface().(time.Time)) 80 | return 81 | 82 | } 83 | 84 | // Otherwise let's switch over all of the 85 | // possible types that this item can be 86 | // and encode it into the correct type. 87 | // For structs, we will cache the struct 88 | // fields, so that we do not have to parse 89 | // these for every item that we process. 90 | 91 | switch k { 92 | 93 | case reflect.Ptr: 94 | w.EncodeReflect(v.Elem()) 95 | 96 | case reflect.Map: 97 | w.encodeMap(v) 98 | 99 | case reflect.Slice: 100 | w.encodeArr(v) 101 | 102 | case reflect.Bool: 103 | w.EncodeBool(v.Bool()) 104 | 105 | case reflect.String: 106 | w.EncodeString(v.String()) 107 | 108 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 109 | w.EncodeInt(int(v.Int())) 110 | 111 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 112 | w.EncodeUint(uint(v.Uint())) 113 | 114 | case reflect.Float32: 115 | w.EncodeFloat32(float32(v.Float())) 116 | 117 | case reflect.Float64: 118 | w.EncodeFloat64(v.Float()) 119 | 120 | case reflect.Complex64: 121 | w.EncodeComplex64(complex64(v.Complex())) 122 | 123 | case reflect.Complex128: 124 | w.EncodeComplex128(v.Complex()) 125 | 126 | case reflect.Interface: 127 | w.EncodeAny(v.Interface()) 128 | 129 | case reflect.Struct: 130 | 131 | if !c.Has(t) { 132 | tot := 0 133 | fls := make([]*field, t.NumField()) 134 | for i := 0; i < t.NumField(); i++ { 135 | if f := newField(t.Field(i)); f != nil { 136 | fls[tot] = f 137 | tot++ 138 | } 139 | } 140 | c.Set(t, fls[:tot]) 141 | } 142 | 143 | sze, fls := 0, c.Get(t) 144 | 145 | for _, f := range fls { 146 | if v := v.FieldByIndex(f.indx); v.IsValid() { 147 | if !f.omit || (f.omit && !isEmpty(v)) { 148 | sze++ 149 | } 150 | } 151 | } 152 | 153 | w.encodeMapLen(sze) 154 | 155 | for _, f := range fls { 156 | if v := v.FieldByIndex(f.indx); v.IsValid() { 157 | if !f.omit || (f.omit && !isEmpty(v)) { 158 | w.EncodeString(f.Name()) 159 | w.EncodeReflect(v) 160 | } 161 | } 162 | } 163 | 164 | } 165 | 166 | } 167 | --------------------------------------------------------------------------------