From 5145b76b8a41b71a7b3c06373959c12f3a22014b Mon Sep 17 00:00:00 2001 From: Taras Madan Date: Mon, 24 Jun 2024 14:30:25 +0200 Subject: vendor: add bigquery client library --- vendor/github.com/apache/arrow/go/v14/LICENSE.txt | 1791 ++++++++ .../apache/arrow/go/v14/arrow/.editorconfig | 21 + .../apache/arrow/go/v14/arrow/.gitignore | 35 + .../apache/arrow/go/v14/arrow/Gopkg.lock | 44 + .../apache/arrow/go/v14/arrow/Gopkg.toml | 23 + .../github.com/apache/arrow/go/v14/arrow/Makefile | 54 + .../github.com/apache/arrow/go/v14/arrow/array.go | 127 + .../apache/arrow/go/v14/arrow/array/array.go | 185 + .../apache/arrow/go/v14/arrow/array/binary.go | 323 ++ .../arrow/go/v14/arrow/array/binarybuilder.go | 375 ++ .../apache/arrow/go/v14/arrow/array/boolean.go | 126 + .../arrow/go/v14/arrow/array/booleanbuilder.go | 263 ++ .../arrow/go/v14/arrow/array/bufferbuilder.go | 153 + .../arrow/go/v14/arrow/array/bufferbuilder_byte.go | 30 + .../v14/arrow/array/bufferbuilder_numeric.gen.go | 124 + .../arrow/array/bufferbuilder_numeric.gen.go.tmpl | 61 + .../apache/arrow/go/v14/arrow/array/builder.go | 369 ++ .../apache/arrow/go/v14/arrow/array/compare.go | 842 ++++ .../apache/arrow/go/v14/arrow/array/concat.go | 910 ++++ .../apache/arrow/go/v14/arrow/array/data.go | 250 + .../apache/arrow/go/v14/arrow/array/decimal128.go | 365 ++ .../apache/arrow/go/v14/arrow/array/decimal256.go | 364 ++ .../apache/arrow/go/v14/arrow/array/dictionary.go | 1953 ++++++++ .../apache/arrow/go/v14/arrow/array/diff.go | 315 ++ .../apache/arrow/go/v14/arrow/array/doc.go | 20 + .../apache/arrow/go/v14/arrow/array/encoded.go | 520 +++ .../apache/arrow/go/v14/arrow/array/extension.go | 244 + .../arrow/go/v14/arrow/array/extension_builder.go | 23 + .../arrow/go/v14/arrow/array/fixed_size_list.go | 372 ++ .../arrow/go/v14/arrow/array/fixedsize_binary.go | 123 + .../go/v14/arrow/array/fixedsize_binarybuilder.go | 261 ++ .../apache/arrow/go/v14/arrow/array/float16.go | 113 + .../arrow/go/v14/arrow/array/float16_builder.go | 263 ++ .../apache/arrow/go/v14/arrow/array/interval.go | 953 ++++ .../apache/arrow/go/v14/arrow/array/json_reader.go | 205 + .../apache/arrow/go/v14/arrow/array/list.go | 1688 +++++++ .../apache/arrow/go/v14/arrow/array/map.go | 361 ++ .../apache/arrow/go/v14/arrow/array/null.go | 218 + .../apache/arrow/go/v14/arrow/array/numeric.gen.go | 1430 ++++++ .../arrow/go/v14/arrow/array/numeric.gen.go.tmpl | 158 + .../arrow/go/v14/arrow/array/numericbuilder.gen.go | 3664 +++++++++++++++ .../go/v14/arrow/array/numericbuilder.gen.go.tmpl | 447 ++ .../arrow/array/numericbuilder.gen_test.go.tmpl | 276 ++ .../apache/arrow/go/v14/arrow/array/record.go | 411 ++ .../apache/arrow/go/v14/arrow/array/string.go | 521 +++ .../apache/arrow/go/v14/arrow/array/struct.go | 491 ++ .../apache/arrow/go/v14/arrow/array/table.go | 421 ++ .../apache/arrow/go/v14/arrow/array/timestamp.go | 381 ++ .../apache/arrow/go/v14/arrow/array/union.go | 1370 ++++++ .../apache/arrow/go/v14/arrow/array/util.go | 523 +++ .../apache/arrow/go/v14/arrow/arrio/arrio.go | 92 + .../apache/arrow/go/v14/arrow/bitutil/Makefile | 62 + .../arrow/go/v14/arrow/bitutil/bitmap_ops.go | 109 + .../arrow/go/v14/arrow/bitutil/bitmap_ops_amd64.go | 41 + .../arrow/go/v14/arrow/bitutil/bitmap_ops_arm64.go | 27 + .../go/v14/arrow/bitutil/bitmap_ops_avx2_amd64.go | 52 + .../go/v14/arrow/bitutil/bitmap_ops_avx2_amd64.s | 373 ++ .../arrow/go/v14/arrow/bitutil/bitmap_ops_noasm.go | 27 + .../go/v14/arrow/bitutil/bitmap_ops_ppc64le.go | 27 + .../arrow/go/v14/arrow/bitutil/bitmap_ops_s390x.go | 27 + .../go/v14/arrow/bitutil/bitmap_ops_sse4_amd64.go | 52 + .../go/v14/arrow/bitutil/bitmap_ops_sse4_amd64.s | 501 ++ .../apache/arrow/go/v14/arrow/bitutil/bitmaps.go | 747 +++ .../apache/arrow/go/v14/arrow/bitutil/bitutil.go | 217 + .../arrow/go/v14/arrow/bitutil/endian_default.go | 33 + .../arrow/go/v14/arrow/bitutil/endian_s390x.go | 32 + .../apache/arrow/go/v14/arrow/compare.go | 153 + .../apache/arrow/go/v14/arrow/datatype.go | 404 ++ .../apache/arrow/go/v14/arrow/datatype_binary.go | 98 + .../apache/arrow/go/v14/arrow/datatype_encoded.go | 67 + .../arrow/go/v14/arrow/datatype_extension.go | 173 + .../arrow/go/v14/arrow/datatype_fixedwidth.go | 819 ++++ .../apache/arrow/go/v14/arrow/datatype_nested.go | 977 ++++ .../apache/arrow/go/v14/arrow/datatype_null.go | 33 + .../arrow/go/v14/arrow/datatype_numeric.gen.go | 206 + .../go/v14/arrow/datatype_numeric.gen.go.tmpl | 45 + .../go/v14/arrow/datatype_numeric.gen.go.tmpldata | 66 + .../arrow/go/v14/arrow/decimal128/decimal128.go | 611 +++ .../arrow/go/v14/arrow/decimal256/decimal256.go | 693 +++ vendor/github.com/apache/arrow/go/v14/arrow/doc.go | 48 + .../apache/arrow/go/v14/arrow/encoded/ree_utils.go | 219 + .../apache/arrow/go/v14/arrow/endian/big.go | 30 + .../apache/arrow/go/v14/arrow/endian/endian.go | 41 + .../apache/arrow/go/v14/arrow/endian/little.go | 30 + .../github.com/apache/arrow/go/v14/arrow/errors.go | 28 + .../apache/arrow/go/v14/arrow/float16/float16.go | 165 + .../go/v14/arrow/internal/debug/assert_off.go | 24 + .../arrow/go/v14/arrow/internal/debug/assert_on.go | 28 + .../arrow/go/v14/arrow/internal/debug/doc.go | 32 + .../arrow/go/v14/arrow/internal/debug/log_off.go | 21 + .../arrow/go/v14/arrow/internal/debug/log_on.go | 32 + .../arrow/go/v14/arrow/internal/debug/util.go | 37 + .../arrow/go/v14/arrow/internal/dictutils/dict.go | 406 ++ .../arrow/go/v14/arrow/internal/flatbuf/Binary.go | 51 + .../go/v14/arrow/internal/flatbuf/BinaryView.go | 57 + .../arrow/go/v14/arrow/internal/flatbuf/Block.go | 74 + .../v14/arrow/internal/flatbuf/BodyCompression.go | 89 + .../internal/flatbuf/BodyCompressionMethod.go | 52 + .../arrow/go/v14/arrow/internal/flatbuf/Bool.go | 50 + .../arrow/go/v14/arrow/internal/flatbuf/Buffer.go | 73 + .../v14/arrow/internal/flatbuf/CompressionType.go | 45 + .../arrow/go/v14/arrow/internal/flatbuf/Date.go | 71 + .../go/v14/arrow/internal/flatbuf/DateUnit.go | 45 + .../arrow/go/v14/arrow/internal/flatbuf/Decimal.go | 107 + .../v14/arrow/internal/flatbuf/DictionaryBatch.go | 108 + .../arrow/internal/flatbuf/DictionaryEncoding.go | 135 + .../v14/arrow/internal/flatbuf/DictionaryKind.go | 47 + .../go/v14/arrow/internal/flatbuf/Duration.go | 65 + .../go/v14/arrow/internal/flatbuf/Endianness.go | 47 + .../arrow/go/v14/arrow/internal/flatbuf/Feature.go | 71 + .../arrow/go/v14/arrow/internal/flatbuf/Field.go | 188 + .../go/v14/arrow/internal/flatbuf/FieldNode.go | 76 + .../v14/arrow/internal/flatbuf/FixedSizeBinary.go | 67 + .../go/v14/arrow/internal/flatbuf/FixedSizeList.go | 67 + .../go/v14/arrow/internal/flatbuf/FloatingPoint.go | 65 + .../arrow/go/v14/arrow/internal/flatbuf/Footer.go | 162 + .../arrow/go/v14/arrow/internal/flatbuf/Int.go | 80 + .../go/v14/arrow/internal/flatbuf/Interval.go | 65 + .../go/v14/arrow/internal/flatbuf/IntervalUnit.go | 48 + .../go/v14/arrow/internal/flatbuf/KeyValue.go | 75 + .../go/v14/arrow/internal/flatbuf/LargeBinary.go | 52 + .../go/v14/arrow/internal/flatbuf/LargeList.go | 52 + .../go/v14/arrow/internal/flatbuf/LargeListView.go | 52 + .../go/v14/arrow/internal/flatbuf/LargeUtf8.go | 52 + .../arrow/go/v14/arrow/internal/flatbuf/List.go | 50 + .../go/v14/arrow/internal/flatbuf/ListView.go | 53 + .../arrow/go/v14/arrow/internal/flatbuf/Map.go | 92 + .../arrow/go/v14/arrow/internal/flatbuf/Message.go | 133 + .../go/v14/arrow/internal/flatbuf/MessageHeader.go | 65 + .../v14/arrow/internal/flatbuf/MetadataVersion.go | 65 + .../arrow/go/v14/arrow/internal/flatbuf/Null.go | 51 + .../go/v14/arrow/internal/flatbuf/Precision.go | 48 + .../go/v14/arrow/internal/flatbuf/RecordBatch.go | 214 + .../go/v14/arrow/internal/flatbuf/RunEndEncoded.go | 55 + .../v14/arrow/internal/flatbuf/RunLengthEncoded.go | 50 + .../arrow/go/v14/arrow/internal/flatbuf/Schema.go | 159 + .../internal/flatbuf/SparseMatrixCompressedAxis.go | 45 + .../arrow/internal/flatbuf/SparseMatrixIndexCSR.go | 181 + .../arrow/internal/flatbuf/SparseMatrixIndexCSX.go | 200 + .../go/v14/arrow/internal/flatbuf/SparseTensor.go | 175 + .../arrow/internal/flatbuf/SparseTensorIndex.go | 51 + .../arrow/internal/flatbuf/SparseTensorIndexCOO.go | 179 + .../arrow/internal/flatbuf/SparseTensorIndexCSF.go | 291 ++ .../arrow/go/v14/arrow/internal/flatbuf/Struct_.go | 53 + .../arrow/go/v14/arrow/internal/flatbuf/Tensor.go | 163 + .../go/v14/arrow/internal/flatbuf/TensorDim.go | 83 + .../arrow/go/v14/arrow/internal/flatbuf/Time.go | 94 + .../go/v14/arrow/internal/flatbuf/TimeUnit.go | 51 + .../go/v14/arrow/internal/flatbuf/Timestamp.go | 201 + .../arrow/go/v14/arrow/internal/flatbuf/Type.go | 123 + .../arrow/go/v14/arrow/internal/flatbuf/Union.go | 101 + .../go/v14/arrow/internal/flatbuf/UnionMode.go | 45 + .../arrow/go/v14/arrow/internal/flatbuf/Utf8.go | 51 + .../go/v14/arrow/internal/flatbuf/Utf8View.go | 57 + .../apache/arrow/go/v14/arrow/internal/utils.go | 47 + .../apache/arrow/go/v14/arrow/ipc/compression.go | 135 + .../apache/arrow/go/v14/arrow/ipc/endian_swap.go | 162 + .../apache/arrow/go/v14/arrow/ipc/file_reader.go | 751 +++ .../apache/arrow/go/v14/arrow/ipc/file_writer.go | 394 ++ .../apache/arrow/go/v14/arrow/ipc/ipc.go | 199 + .../apache/arrow/go/v14/arrow/ipc/message.go | 242 + .../apache/arrow/go/v14/arrow/ipc/metadata.go | 1287 ++++++ .../apache/arrow/go/v14/arrow/ipc/reader.go | 285 ++ .../apache/arrow/go/v14/arrow/ipc/writer.go | 1004 ++++ .../apache/arrow/go/v14/arrow/memory/Makefile | 66 + .../apache/arrow/go/v14/arrow/memory/allocator.go | 27 + .../apache/arrow/go/v14/arrow/memory/buffer.go | 145 + .../arrow/go/v14/arrow/memory/cgo_allocator.go | 108 + .../go/v14/arrow/memory/cgo_allocator_defaults.go | 23 + .../go/v14/arrow/memory/cgo_allocator_logging.go | 23 + .../arrow/go/v14/arrow/memory/checked_allocator.go | 221 + .../arrow/go/v14/arrow/memory/default_allocator.go | 25 + .../go/v14/arrow/memory/default_mallocator.go | 29 + .../apache/arrow/go/v14/arrow/memory/doc.go | 22 + .../arrow/go/v14/arrow/memory/go_allocator.go | 47 + .../arrow/memory/internal/cgoalloc/allocator.cc | 71 + .../arrow/memory/internal/cgoalloc/allocator.go | 108 + .../v14/arrow/memory/internal/cgoalloc/allocator.h | 39 + .../v14/arrow/memory/internal/cgoalloc/helpers.h | 52 + .../arrow/go/v14/arrow/memory/mallocator/doc.go | 21 + .../go/v14/arrow/memory/mallocator/mallocator.go | 115 + .../apache/arrow/go/v14/arrow/memory/memory.go | 33 + .../arrow/go/v14/arrow/memory/memory_amd64.go | 33 + .../arrow/go/v14/arrow/memory/memory_arm64.go | 31 + .../arrow/go/v14/arrow/memory/memory_avx2_amd64.go | 41 + .../arrow/go/v14/arrow/memory/memory_avx2_amd64.s | 85 + .../arrow/go/v14/arrow/memory/memory_js_wasm.go | 23 + .../arrow/go/v14/arrow/memory/memory_neon_arm64.go | 31 + .../arrow/go/v14/arrow/memory/memory_neon_arm64.s | 43 + .../arrow/go/v14/arrow/memory/memory_noasm.go | 23 + .../arrow/go/v14/arrow/memory/memory_sse4_amd64.go | 31 + .../arrow/go/v14/arrow/memory/memory_sse4_amd64.s | 84 + .../apache/arrow/go/v14/arrow/memory/util.go | 37 + .../apache/arrow/go/v14/arrow/numeric.schema.json | 15 + .../apache/arrow/go/v14/arrow/numeric.tmpldata | 135 + .../github.com/apache/arrow/go/v14/arrow/record.go | 49 + .../github.com/apache/arrow/go/v14/arrow/schema.go | 301 ++ .../github.com/apache/arrow/go/v14/arrow/table.go | 193 + .../github.com/apache/arrow/go/v14/arrow/tools.go | 25 + .../apache/arrow/go/v14/arrow/type_string.go | 65 + .../arrow/go/v14/arrow/type_traits_boolean.go | 28 + .../arrow/go/v14/arrow/type_traits_decimal128.go | 63 + .../arrow/go/v14/arrow/type_traits_decimal256.go | 58 + .../arrow/go/v14/arrow/type_traits_float16.go | 62 + .../arrow/go/v14/arrow/type_traits_interval.go | 148 + .../arrow/go/v14/arrow/type_traits_numeric.gen.go | 585 +++ .../go/v14/arrow/type_traits_numeric.gen.go.tmpl | 83 + .../v14/arrow/type_traits_numeric.gen_test.go.tmpl | 61 + .../arrow/go/v14/arrow/type_traits_timestamp.go | 59 + .../apache/arrow/go/v14/arrow/unionmode_string.go | 25 + .../go/v14/internal/bitutils/bit_block_counter.go | 452 ++ .../go/v14/internal/bitutils/bit_run_reader.go | 151 + .../go/v14/internal/bitutils/bit_set_run_reader.go | 361 ++ .../go/v14/internal/bitutils/bitmap_generate.go | 109 + .../arrow/go/v14/internal/hashing/hash_funcs.go | 90 + .../arrow/go/v14/internal/hashing/hash_string.go | 26 + .../go/v14/internal/hashing/hash_string_go1.19.go | 37 + .../arrow/go/v14/internal/hashing/types.tmpldata | 42 + .../go/v14/internal/hashing/xxh3_memo_table.gen.go | 2833 ++++++++++++ .../internal/hashing/xxh3_memo_table.gen.go.tmpl | 349 ++ .../go/v14/internal/hashing/xxh3_memo_table.go | 443 ++ .../apache/arrow/go/v14/internal/json/json.go | 51 + .../arrow/go/v14/internal/json/json_tinygo.go | 51 + .../apache/arrow/go/v14/internal/utils/Makefile | 80 + .../arrow/go/v14/internal/utils/buf_reader.go | 212 + .../arrow/go/v14/internal/utils/endians_default.go | 30 + .../arrow/go/v14/internal/utils/endians_s390x.go | 33 + .../apache/arrow/go/v14/internal/utils/math.go | 49 + .../apache/arrow/go/v14/internal/utils/min_max.go | 212 + .../arrow/go/v14/internal/utils/min_max_amd64.go | 55 + .../arrow/go/v14/internal/utils/min_max_arm64.go | 65 + .../go/v14/internal/utils/min_max_avx2_amd64.go | 90 + .../go/v14/internal/utils/min_max_avx2_amd64.s | 927 ++++ .../go/v14/internal/utils/min_max_neon_arm64.go | 56 + .../go/v14/internal/utils/min_max_neon_arm64.s | 324 ++ .../arrow/go/v14/internal/utils/min_max_noasm.go | 31 + .../arrow/go/v14/internal/utils/min_max_ppc64le.go | 30 + .../arrow/go/v14/internal/utils/min_max_s390x.go | 30 + .../go/v14/internal/utils/min_max_sse4_amd64.go | 88 + .../go/v14/internal/utils/min_max_sse4_amd64.s | 1044 +++++ .../arrow/go/v14/internal/utils/transpose_ints.go | 407 ++ .../go/v14/internal/utils/transpose_ints.go.tmpl | 34 + .../go/v14/internal/utils/transpose_ints.tmpldata | 34 + .../go/v14/internal/utils/transpose_ints_amd64.go | 325 ++ .../internal/utils/transpose_ints_amd64.go.tmpl | 75 + .../go/v14/internal/utils/transpose_ints_arm64.go | 96 + .../internal/utils/transpose_ints_avx2_amd64.go | 473 ++ .../v14/internal/utils/transpose_ints_avx2_amd64.s | 3074 +++++++++++++ .../go/v14/internal/utils/transpose_ints_def.go | 227 + .../go/v14/internal/utils/transpose_ints_noasm.go | 96 + .../internal/utils/transpose_ints_noasm.go.tmpl | 34 + .../v14/internal/utils/transpose_ints_ppc64le.go | 96 + .../go/v14/internal/utils/transpose_ints_s390x.go | 96 + .../internal/utils/transpose_ints_s390x.go.tmpl | 34 + .../v14/internal/utils/transpose_ints_simd.go.tmpl | 42 + .../internal/utils/transpose_ints_sse4_amd64.go | 473 ++ .../v14/internal/utils/transpose_ints_sse4_amd64.s | 3074 +++++++++++++ vendor/github.com/goccy/go-json/.codecov.yml | 32 + vendor/github.com/goccy/go-json/.gitignore | 2 + vendor/github.com/goccy/go-json/.golangci.yml | 83 + vendor/github.com/goccy/go-json/CHANGELOG.md | 425 ++ vendor/github.com/goccy/go-json/LICENSE | 21 + vendor/github.com/goccy/go-json/Makefile | 39 + vendor/github.com/goccy/go-json/README.md | 529 +++ vendor/github.com/goccy/go-json/color.go | 68 + vendor/github.com/goccy/go-json/decode.go | 263 ++ vendor/github.com/goccy/go-json/docker-compose.yml | 13 + vendor/github.com/goccy/go-json/encode.go | 326 ++ vendor/github.com/goccy/go-json/error.go | 41 + .../go-json/internal/decoder/anonymous_field.go | 41 + .../goccy/go-json/internal/decoder/array.go | 176 + .../goccy/go-json/internal/decoder/assign.go | 438 ++ .../goccy/go-json/internal/decoder/bool.go | 83 + .../goccy/go-json/internal/decoder/bytes.go | 118 + .../goccy/go-json/internal/decoder/compile.go | 487 ++ .../go-json/internal/decoder/compile_norace.go | 29 + .../goccy/go-json/internal/decoder/compile_race.go | 37 + .../goccy/go-json/internal/decoder/context.go | 254 + .../goccy/go-json/internal/decoder/float.go | 170 + .../goccy/go-json/internal/decoder/func.go | 146 + .../goccy/go-json/internal/decoder/int.go | 246 + .../goccy/go-json/internal/decoder/interface.go | 528 +++ .../goccy/go-json/internal/decoder/invalid.go | 55 + .../goccy/go-json/internal/decoder/map.go | 280 ++ .../goccy/go-json/internal/decoder/number.go | 123 + .../goccy/go-json/internal/decoder/option.go | 17 + .../goccy/go-json/internal/decoder/path.go | 670 +++ .../goccy/go-json/internal/decoder/ptr.go | 96 + .../goccy/go-json/internal/decoder/slice.go | 380 ++ .../goccy/go-json/internal/decoder/stream.go | 556 +++ .../goccy/go-json/internal/decoder/string.go | 452 ++ .../goccy/go-json/internal/decoder/struct.go | 845 ++++ .../goccy/go-json/internal/decoder/type.go | 30 + .../goccy/go-json/internal/decoder/uint.go | 194 + .../go-json/internal/decoder/unmarshal_json.go | 104 + .../go-json/internal/decoder/unmarshal_text.go | 285 ++ .../go-json/internal/decoder/wrapped_string.go | 73 + .../goccy/go-json/internal/encoder/code.go | 1023 +++++ .../goccy/go-json/internal/encoder/compact.go | 286 ++ .../goccy/go-json/internal/encoder/compiler.go | 935 ++++ .../go-json/internal/encoder/compiler_norace.go | 32 + .../go-json/internal/encoder/compiler_race.go | 45 + .../goccy/go-json/internal/encoder/context.go | 105 + .../goccy/go-json/internal/encoder/decode_rune.go | 126 + .../goccy/go-json/internal/encoder/encoder.go | 596 +++ .../goccy/go-json/internal/encoder/indent.go | 211 + .../goccy/go-json/internal/encoder/int.go | 152 + .../goccy/go-json/internal/encoder/map112.go | 9 + .../goccy/go-json/internal/encoder/map113.go | 9 + .../goccy/go-json/internal/encoder/opcode.go | 752 +++ .../goccy/go-json/internal/encoder/option.go | 48 + .../goccy/go-json/internal/encoder/optype.go | 932 ++++ .../goccy/go-json/internal/encoder/query.go | 135 + .../goccy/go-json/internal/encoder/string.go | 459 ++ .../goccy/go-json/internal/encoder/string_table.go | 415 ++ .../goccy/go-json/internal/encoder/vm/debug_vm.go | 41 + .../goccy/go-json/internal/encoder/vm/hack.go | 9 + .../goccy/go-json/internal/encoder/vm/util.go | 207 + .../goccy/go-json/internal/encoder/vm/vm.go | 4859 ++++++++++++++++++++ .../go-json/internal/encoder/vm_color/debug_vm.go | 35 + .../go-json/internal/encoder/vm_color/hack.go | 9 + .../go-json/internal/encoder/vm_color/util.go | 274 ++ .../goccy/go-json/internal/encoder/vm_color/vm.go | 4859 ++++++++++++++++++++ .../internal/encoder/vm_color_indent/debug_vm.go | 35 + .../internal/encoder/vm_color_indent/util.go | 297 ++ .../go-json/internal/encoder/vm_color_indent/vm.go | 4859 ++++++++++++++++++++ .../go-json/internal/encoder/vm_indent/debug_vm.go | 35 + .../go-json/internal/encoder/vm_indent/hack.go | 9 + .../go-json/internal/encoder/vm_indent/util.go | 230 + .../goccy/go-json/internal/encoder/vm_indent/vm.go | 4859 ++++++++++++++++++++ .../goccy/go-json/internal/errors/error.go | 183 + .../goccy/go-json/internal/runtime/rtype.go | 263 ++ .../goccy/go-json/internal/runtime/struct_field.go | 91 + .../goccy/go-json/internal/runtime/type.go | 100 + vendor/github.com/goccy/go-json/json.go | 371 ++ vendor/github.com/goccy/go-json/option.go | 79 + vendor/github.com/goccy/go-json/path.go | 84 + vendor/github.com/goccy/go-json/query.go | 47 + .../github.com/klauspost/compress/.gitattributes | 2 + vendor/github.com/klauspost/compress/.gitignore | 32 + .../github.com/klauspost/compress/.goreleaser.yml | 141 + vendor/github.com/klauspost/compress/LICENSE | 304 ++ vendor/github.com/klauspost/compress/README.md | 642 +++ vendor/github.com/klauspost/compress/SECURITY.md | 25 + .../github.com/klauspost/compress/compressible.go | 85 + vendor/github.com/klauspost/compress/fse/README.md | 79 + .../github.com/klauspost/compress/fse/bitreader.go | 122 + .../github.com/klauspost/compress/fse/bitwriter.go | 168 + .../klauspost/compress/fse/bytereader.go | 47 + .../github.com/klauspost/compress/fse/compress.go | 682 +++ .../klauspost/compress/fse/decompress.go | 376 ++ vendor/github.com/klauspost/compress/fse/fse.go | 144 + vendor/github.com/klauspost/compress/gen.sh | 4 + .../github.com/klauspost/compress/huff0/.gitignore | 1 + .../github.com/klauspost/compress/huff0/README.md | 89 + .../klauspost/compress/huff0/bitreader.go | 229 + .../klauspost/compress/huff0/bitwriter.go | 103 + .../klauspost/compress/huff0/bytereader.go | 44 + .../klauspost/compress/huff0/compress.go | 749 +++ .../klauspost/compress/huff0/decompress.go | 1167 +++++ .../klauspost/compress/huff0/decompress_amd64.go | 226 + .../klauspost/compress/huff0/decompress_amd64.s | 830 ++++ .../klauspost/compress/huff0/decompress_generic.go | 299 ++ .../github.com/klauspost/compress/huff0/huff0.go | 337 ++ .../klauspost/compress/internal/cpuinfo/cpuinfo.go | 34 + .../compress/internal/cpuinfo/cpuinfo_amd64.go | 11 + .../compress/internal/cpuinfo/cpuinfo_amd64.s | 36 + .../klauspost/compress/internal/snapref/LICENSE | 27 + .../klauspost/compress/internal/snapref/decode.go | 264 ++ .../compress/internal/snapref/decode_other.go | 113 + .../klauspost/compress/internal/snapref/encode.go | 289 ++ .../compress/internal/snapref/encode_other.go | 250 + .../klauspost/compress/internal/snapref/snappy.go | 98 + vendor/github.com/klauspost/compress/s2sx.mod | 4 + vendor/github.com/klauspost/compress/s2sx.sum | 0 .../github.com/klauspost/compress/zstd/README.md | 441 ++ .../klauspost/compress/zstd/bitreader.go | 140 + .../klauspost/compress/zstd/bitwriter.go | 113 + .../github.com/klauspost/compress/zstd/blockdec.go | 726 +++ .../github.com/klauspost/compress/zstd/blockenc.go | 874 ++++ .../klauspost/compress/zstd/blocktype_string.go | 85 + .../github.com/klauspost/compress/zstd/bytebuf.go | 131 + .../klauspost/compress/zstd/bytereader.go | 82 + .../klauspost/compress/zstd/decodeheader.go | 229 + .../github.com/klauspost/compress/zstd/decoder.go | 948 ++++ .../klauspost/compress/zstd/decoder_options.go | 169 + vendor/github.com/klauspost/compress/zstd/dict.go | 161 + .../github.com/klauspost/compress/zstd/enc_base.go | 173 + .../github.com/klauspost/compress/zstd/enc_best.go | 530 +++ .../klauspost/compress/zstd/enc_better.go | 1242 +++++ .../klauspost/compress/zstd/enc_dfast.go | 1123 +++++ .../github.com/klauspost/compress/zstd/enc_fast.go | 891 ++++ .../github.com/klauspost/compress/zstd/encoder.go | 624 +++ .../klauspost/compress/zstd/encoder_options.go | 339 ++ .../github.com/klauspost/compress/zstd/framedec.go | 413 ++ .../github.com/klauspost/compress/zstd/frameenc.go | 137 + .../klauspost/compress/zstd/fse_decoder.go | 307 ++ .../klauspost/compress/zstd/fse_decoder_amd64.go | 65 + .../klauspost/compress/zstd/fse_decoder_amd64.s | 126 + .../klauspost/compress/zstd/fse_decoder_generic.go | 72 + .../klauspost/compress/zstd/fse_encoder.go | 701 +++ .../klauspost/compress/zstd/fse_predefined.go | 158 + vendor/github.com/klauspost/compress/zstd/hash.go | 35 + .../github.com/klauspost/compress/zstd/history.go | 116 + .../compress/zstd/internal/xxhash/LICENSE.txt | 22 + .../compress/zstd/internal/xxhash/README.md | 71 + .../compress/zstd/internal/xxhash/xxhash.go | 230 + .../compress/zstd/internal/xxhash/xxhash_amd64.s | 210 + .../compress/zstd/internal/xxhash/xxhash_arm64.s | 184 + .../compress/zstd/internal/xxhash/xxhash_asm.go | 16 + .../compress/zstd/internal/xxhash/xxhash_other.go | 76 + .../compress/zstd/internal/xxhash/xxhash_safe.go | 11 + .../klauspost/compress/zstd/matchlen_amd64.go | 16 + .../klauspost/compress/zstd/matchlen_amd64.s | 68 + .../klauspost/compress/zstd/matchlen_generic.go | 33 + .../github.com/klauspost/compress/zstd/seqdec.go | 508 ++ .../klauspost/compress/zstd/seqdec_amd64.go | 394 ++ .../klauspost/compress/zstd/seqdec_amd64.s | 4175 +++++++++++++++++ .../klauspost/compress/zstd/seqdec_generic.go | 237 + .../github.com/klauspost/compress/zstd/seqenc.go | 114 + .../github.com/klauspost/compress/zstd/snappy.go | 435 ++ vendor/github.com/klauspost/compress/zstd/zip.go | 141 + vendor/github.com/klauspost/compress/zstd/zstd.go | 121 + vendor/github.com/klauspost/cpuid/v2/.gitignore | 24 + .../github.com/klauspost/cpuid/v2/.goreleaser.yml | 74 + .../github.com/klauspost/cpuid/v2/CONTRIBUTING.txt | 35 + vendor/github.com/klauspost/cpuid/v2/LICENSE | 22 + vendor/github.com/klauspost/cpuid/v2/README.md | 493 ++ vendor/github.com/klauspost/cpuid/v2/cpuid.go | 1427 ++++++ vendor/github.com/klauspost/cpuid/v2/cpuid_386.s | 47 + vendor/github.com/klauspost/cpuid/v2/cpuid_amd64.s | 72 + vendor/github.com/klauspost/cpuid/v2/cpuid_arm64.s | 26 + .../github.com/klauspost/cpuid/v2/detect_arm64.go | 247 + vendor/github.com/klauspost/cpuid/v2/detect_ref.go | 15 + vendor/github.com/klauspost/cpuid/v2/detect_x86.go | 36 + .../klauspost/cpuid/v2/featureid_string.go | 272 ++ .../klauspost/cpuid/v2/os_darwin_arm64.go | 121 + .../klauspost/cpuid/v2/os_linux_arm64.go | 130 + .../klauspost/cpuid/v2/os_other_arm64.go | 16 + .../klauspost/cpuid/v2/os_safe_linux_arm64.go | 8 + .../klauspost/cpuid/v2/os_unsafe_linux_arm64.go | 11 + .../klauspost/cpuid/v2/test-architectures.sh | 15 + vendor/github.com/pierrec/lz4/v4/.gitignore | 36 + vendor/github.com/pierrec/lz4/v4/LICENSE | 28 + vendor/github.com/pierrec/lz4/v4/README.md | 92 + .../pierrec/lz4/v4/internal/lz4block/block.go | 481 ++ .../pierrec/lz4/v4/internal/lz4block/blocks.go | 90 + .../lz4/v4/internal/lz4block/decode_amd64.s | 448 ++ .../pierrec/lz4/v4/internal/lz4block/decode_arm.s | 231 + .../lz4/v4/internal/lz4block/decode_arm64.s | 241 + .../pierrec/lz4/v4/internal/lz4block/decode_asm.go | 10 + .../lz4/v4/internal/lz4block/decode_other.go | 139 + .../pierrec/lz4/v4/internal/lz4errors/errors.go | 19 + .../pierrec/lz4/v4/internal/lz4stream/block.go | 350 ++ .../pierrec/lz4/v4/internal/lz4stream/frame.go | 204 + .../pierrec/lz4/v4/internal/lz4stream/frame_gen.go | 103 + .../pierrec/lz4/v4/internal/xxh32/xxh32zero.go | 212 + .../pierrec/lz4/v4/internal/xxh32/xxh32zero_arm.go | 11 + .../pierrec/lz4/v4/internal/xxh32/xxh32zero_arm.s | 251 + .../lz4/v4/internal/xxh32/xxh32zero_other.go | 10 + vendor/github.com/pierrec/lz4/v4/lz4.go | 157 + vendor/github.com/pierrec/lz4/v4/options.go | 214 + vendor/github.com/pierrec/lz4/v4/options_gen.go | 92 + vendor/github.com/pierrec/lz4/v4/reader.go | 275 ++ vendor/github.com/pierrec/lz4/v4/state.go | 75 + vendor/github.com/pierrec/lz4/v4/state_gen.go | 28 + vendor/github.com/pierrec/lz4/v4/writer.go | 238 + vendor/github.com/zeebo/xxh3/.gitignore | 6 + vendor/github.com/zeebo/xxh3/LICENSE | 25 + vendor/github.com/zeebo/xxh3/Makefile | 27 + vendor/github.com/zeebo/xxh3/README.md | 38 + vendor/github.com/zeebo/xxh3/_compat.c | 39 + vendor/github.com/zeebo/xxh3/accum_generic.go | 542 +++ vendor/github.com/zeebo/xxh3/accum_stubs_amd64.go | 40 + vendor/github.com/zeebo/xxh3/accum_stubs_other.go | 25 + .../zeebo/xxh3/accum_vector_avx512_amd64.s | 379 ++ .../github.com/zeebo/xxh3/accum_vector_avx_amd64.s | 586 +++ .../github.com/zeebo/xxh3/accum_vector_sse_amd64.s | 1236 +++++ vendor/github.com/zeebo/xxh3/consts.go | 97 + vendor/github.com/zeebo/xxh3/hash128.go | 253 + vendor/github.com/zeebo/xxh3/hash128_seed.go | 264 ++ vendor/github.com/zeebo/xxh3/hash64.go | 126 + vendor/github.com/zeebo/xxh3/hash64_seed.go | 134 + vendor/github.com/zeebo/xxh3/hasher.go | 239 + vendor/github.com/zeebo/xxh3/utils.go | 129 + 485 files changed, 137508 insertions(+) create mode 100644 vendor/github.com/apache/arrow/go/v14/LICENSE.txt create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/.editorconfig create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/.gitignore create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/Gopkg.lock create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/Gopkg.toml create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/Makefile create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array/array.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array/binary.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array/binarybuilder.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array/boolean.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array/booleanbuilder.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array/bufferbuilder.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array/bufferbuilder_byte.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array/bufferbuilder_numeric.gen.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array/bufferbuilder_numeric.gen.go.tmpl create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array/builder.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array/compare.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array/concat.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array/data.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array/decimal128.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array/decimal256.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array/dictionary.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array/diff.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array/doc.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array/encoded.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array/extension.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array/extension_builder.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array/fixed_size_list.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array/fixedsize_binary.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array/fixedsize_binarybuilder.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array/float16.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array/float16_builder.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array/interval.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array/json_reader.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array/list.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array/map.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array/null.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array/numeric.gen.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array/numeric.gen.go.tmpl create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array/numericbuilder.gen.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array/numericbuilder.gen.go.tmpl create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array/numericbuilder.gen_test.go.tmpl create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array/record.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array/string.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array/struct.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array/table.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array/timestamp.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array/union.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/array/util.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/arrio/arrio.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/bitutil/Makefile create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmap_ops.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmap_ops_amd64.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmap_ops_arm64.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmap_ops_avx2_amd64.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmap_ops_avx2_amd64.s create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmap_ops_noasm.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmap_ops_ppc64le.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmap_ops_s390x.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmap_ops_sse4_amd64.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmap_ops_sse4_amd64.s create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmaps.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitutil.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/bitutil/endian_default.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/bitutil/endian_s390x.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/compare.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/datatype.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/datatype_binary.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/datatype_encoded.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/datatype_extension.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/datatype_fixedwidth.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/datatype_nested.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/datatype_null.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/datatype_numeric.gen.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/datatype_numeric.gen.go.tmpl create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/datatype_numeric.gen.go.tmpldata create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/decimal128/decimal128.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/decimal256/decimal256.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/doc.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/encoded/ree_utils.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/endian/big.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/endian/endian.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/endian/little.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/errors.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/float16/float16.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/debug/assert_off.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/debug/assert_on.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/debug/doc.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/debug/log_off.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/debug/log_on.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/debug/util.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/dictutils/dict.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Binary.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/BinaryView.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Block.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/BodyCompression.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/BodyCompressionMethod.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Bool.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Buffer.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/CompressionType.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Date.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/DateUnit.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Decimal.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/DictionaryBatch.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/DictionaryEncoding.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/DictionaryKind.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Duration.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Endianness.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Feature.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Field.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/FieldNode.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/FixedSizeBinary.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/FixedSizeList.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/FloatingPoint.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Footer.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Int.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Interval.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/IntervalUnit.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/KeyValue.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/LargeBinary.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/LargeList.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/LargeListView.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/LargeUtf8.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/List.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/ListView.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Map.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Message.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/MessageHeader.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/MetadataVersion.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Null.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Precision.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/RecordBatch.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/RunEndEncoded.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/RunLengthEncoded.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Schema.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/SparseMatrixCompressedAxis.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/SparseMatrixIndexCSR.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/SparseMatrixIndexCSX.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/SparseTensor.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/SparseTensorIndex.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/SparseTensorIndexCOO.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/SparseTensorIndexCSF.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Struct_.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Tensor.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/TensorDim.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Time.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/TimeUnit.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Timestamp.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Type.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Union.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/UnionMode.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Utf8.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Utf8View.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/internal/utils.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/ipc/compression.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/ipc/endian_swap.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/ipc/file_reader.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/ipc/file_writer.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/ipc/ipc.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/ipc/message.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/ipc/metadata.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/ipc/reader.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/ipc/writer.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/memory/Makefile create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/memory/allocator.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/memory/buffer.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/memory/cgo_allocator.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/memory/cgo_allocator_defaults.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/memory/cgo_allocator_logging.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/memory/checked_allocator.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/memory/default_allocator.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/memory/default_mallocator.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/memory/doc.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/memory/go_allocator.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/memory/internal/cgoalloc/allocator.cc create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/memory/internal/cgoalloc/allocator.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/memory/internal/cgoalloc/allocator.h create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/memory/internal/cgoalloc/helpers.h create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/memory/mallocator/doc.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/memory/mallocator/mallocator.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/memory/memory.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/memory/memory_amd64.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/memory/memory_arm64.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/memory/memory_avx2_amd64.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/memory/memory_avx2_amd64.s create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/memory/memory_js_wasm.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/memory/memory_neon_arm64.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/memory/memory_neon_arm64.s create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/memory/memory_noasm.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/memory/memory_sse4_amd64.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/memory/memory_sse4_amd64.s create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/memory/util.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/numeric.schema.json create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/numeric.tmpldata create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/record.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/schema.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/table.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/tools.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/type_string.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/type_traits_boolean.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/type_traits_decimal128.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/type_traits_decimal256.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/type_traits_float16.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/type_traits_interval.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/type_traits_numeric.gen.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/type_traits_numeric.gen.go.tmpl create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/type_traits_numeric.gen_test.go.tmpl create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/type_traits_timestamp.go create mode 100644 vendor/github.com/apache/arrow/go/v14/arrow/unionmode_string.go create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/bitutils/bit_block_counter.go create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/bitutils/bit_run_reader.go create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/bitutils/bit_set_run_reader.go create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/bitutils/bitmap_generate.go create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/hashing/hash_funcs.go create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/hashing/hash_string.go create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/hashing/hash_string_go1.19.go create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/hashing/types.tmpldata create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/hashing/xxh3_memo_table.gen.go create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/hashing/xxh3_memo_table.gen.go.tmpl create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/hashing/xxh3_memo_table.go create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/json/json.go create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/json/json_tinygo.go create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/utils/Makefile create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/utils/buf_reader.go create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/utils/endians_default.go create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/utils/endians_s390x.go create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/utils/math.go create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/utils/min_max.go create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_amd64.go create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_arm64.go create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_avx2_amd64.go create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_avx2_amd64.s create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_neon_arm64.go create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_neon_arm64.s create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_noasm.go create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_ppc64le.go create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_s390x.go create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_sse4_amd64.go create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_sse4_amd64.s create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints.go create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints.go.tmpl create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints.tmpldata create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_amd64.go create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_amd64.go.tmpl create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_arm64.go create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_avx2_amd64.go create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_avx2_amd64.s create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_def.go create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_noasm.go create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_noasm.go.tmpl create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_ppc64le.go create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_s390x.go create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_s390x.go.tmpl create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_simd.go.tmpl create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_sse4_amd64.go create mode 100644 vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_sse4_amd64.s create mode 100644 vendor/github.com/goccy/go-json/.codecov.yml create mode 100644 vendor/github.com/goccy/go-json/.gitignore create mode 100644 vendor/github.com/goccy/go-json/.golangci.yml create mode 100644 vendor/github.com/goccy/go-json/CHANGELOG.md create mode 100644 vendor/github.com/goccy/go-json/LICENSE create mode 100644 vendor/github.com/goccy/go-json/Makefile create mode 100644 vendor/github.com/goccy/go-json/README.md create mode 100644 vendor/github.com/goccy/go-json/color.go create mode 100644 vendor/github.com/goccy/go-json/decode.go create mode 100644 vendor/github.com/goccy/go-json/docker-compose.yml create mode 100644 vendor/github.com/goccy/go-json/encode.go create mode 100644 vendor/github.com/goccy/go-json/error.go create mode 100644 vendor/github.com/goccy/go-json/internal/decoder/anonymous_field.go create mode 100644 vendor/github.com/goccy/go-json/internal/decoder/array.go create mode 100644 vendor/github.com/goccy/go-json/internal/decoder/assign.go create mode 100644 vendor/github.com/goccy/go-json/internal/decoder/bool.go create mode 100644 vendor/github.com/goccy/go-json/internal/decoder/bytes.go create mode 100644 vendor/github.com/goccy/go-json/internal/decoder/compile.go create mode 100644 vendor/github.com/goccy/go-json/internal/decoder/compile_norace.go create mode 100644 vendor/github.com/goccy/go-json/internal/decoder/compile_race.go create mode 100644 vendor/github.com/goccy/go-json/internal/decoder/context.go create mode 100644 vendor/github.com/goccy/go-json/internal/decoder/float.go create mode 100644 vendor/github.com/goccy/go-json/internal/decoder/func.go create mode 100644 vendor/github.com/goccy/go-json/internal/decoder/int.go create mode 100644 vendor/github.com/goccy/go-json/internal/decoder/interface.go create mode 100644 vendor/github.com/goccy/go-json/internal/decoder/invalid.go create mode 100644 vendor/github.com/goccy/go-json/internal/decoder/map.go create mode 100644 vendor/github.com/goccy/go-json/internal/decoder/number.go create mode 100644 vendor/github.com/goccy/go-json/internal/decoder/option.go create mode 100644 vendor/github.com/goccy/go-json/internal/decoder/path.go create mode 100644 vendor/github.com/goccy/go-json/internal/decoder/ptr.go create mode 100644 vendor/github.com/goccy/go-json/internal/decoder/slice.go create mode 100644 vendor/github.com/goccy/go-json/internal/decoder/stream.go create mode 100644 vendor/github.com/goccy/go-json/internal/decoder/string.go create mode 100644 vendor/github.com/goccy/go-json/internal/decoder/struct.go create mode 100644 vendor/github.com/goccy/go-json/internal/decoder/type.go create mode 100644 vendor/github.com/goccy/go-json/internal/decoder/uint.go create mode 100644 vendor/github.com/goccy/go-json/internal/decoder/unmarshal_json.go create mode 100644 vendor/github.com/goccy/go-json/internal/decoder/unmarshal_text.go create mode 100644 vendor/github.com/goccy/go-json/internal/decoder/wrapped_string.go create mode 100644 vendor/github.com/goccy/go-json/internal/encoder/code.go create mode 100644 vendor/github.com/goccy/go-json/internal/encoder/compact.go create mode 100644 vendor/github.com/goccy/go-json/internal/encoder/compiler.go create mode 100644 vendor/github.com/goccy/go-json/internal/encoder/compiler_norace.go create mode 100644 vendor/github.com/goccy/go-json/internal/encoder/compiler_race.go create mode 100644 vendor/github.com/goccy/go-json/internal/encoder/context.go create mode 100644 vendor/github.com/goccy/go-json/internal/encoder/decode_rune.go create mode 100644 vendor/github.com/goccy/go-json/internal/encoder/encoder.go create mode 100644 vendor/github.com/goccy/go-json/internal/encoder/indent.go create mode 100644 vendor/github.com/goccy/go-json/internal/encoder/int.go create mode 100644 vendor/github.com/goccy/go-json/internal/encoder/map112.go create mode 100644 vendor/github.com/goccy/go-json/internal/encoder/map113.go create mode 100644 vendor/github.com/goccy/go-json/internal/encoder/opcode.go create mode 100644 vendor/github.com/goccy/go-json/internal/encoder/option.go create mode 100644 vendor/github.com/goccy/go-json/internal/encoder/optype.go create mode 100644 vendor/github.com/goccy/go-json/internal/encoder/query.go create mode 100644 vendor/github.com/goccy/go-json/internal/encoder/string.go create mode 100644 vendor/github.com/goccy/go-json/internal/encoder/string_table.go create mode 100644 vendor/github.com/goccy/go-json/internal/encoder/vm/debug_vm.go create mode 100644 vendor/github.com/goccy/go-json/internal/encoder/vm/hack.go create mode 100644 vendor/github.com/goccy/go-json/internal/encoder/vm/util.go create mode 100644 vendor/github.com/goccy/go-json/internal/encoder/vm/vm.go create mode 100644 vendor/github.com/goccy/go-json/internal/encoder/vm_color/debug_vm.go create mode 100644 vendor/github.com/goccy/go-json/internal/encoder/vm_color/hack.go create mode 100644 vendor/github.com/goccy/go-json/internal/encoder/vm_color/util.go create mode 100644 vendor/github.com/goccy/go-json/internal/encoder/vm_color/vm.go create mode 100644 vendor/github.com/goccy/go-json/internal/encoder/vm_color_indent/debug_vm.go create mode 100644 vendor/github.com/goccy/go-json/internal/encoder/vm_color_indent/util.go create mode 100644 vendor/github.com/goccy/go-json/internal/encoder/vm_color_indent/vm.go create mode 100644 vendor/github.com/goccy/go-json/internal/encoder/vm_indent/debug_vm.go create mode 100644 vendor/github.com/goccy/go-json/internal/encoder/vm_indent/hack.go create mode 100644 vendor/github.com/goccy/go-json/internal/encoder/vm_indent/util.go create mode 100644 vendor/github.com/goccy/go-json/internal/encoder/vm_indent/vm.go create mode 100644 vendor/github.com/goccy/go-json/internal/errors/error.go create mode 100644 vendor/github.com/goccy/go-json/internal/runtime/rtype.go create mode 100644 vendor/github.com/goccy/go-json/internal/runtime/struct_field.go create mode 100644 vendor/github.com/goccy/go-json/internal/runtime/type.go create mode 100644 vendor/github.com/goccy/go-json/json.go create mode 100644 vendor/github.com/goccy/go-json/option.go create mode 100644 vendor/github.com/goccy/go-json/path.go create mode 100644 vendor/github.com/goccy/go-json/query.go create mode 100644 vendor/github.com/klauspost/compress/.gitattributes create mode 100644 vendor/github.com/klauspost/compress/.gitignore create mode 100644 vendor/github.com/klauspost/compress/.goreleaser.yml create mode 100644 vendor/github.com/klauspost/compress/LICENSE create mode 100644 vendor/github.com/klauspost/compress/README.md create mode 100644 vendor/github.com/klauspost/compress/SECURITY.md create mode 100644 vendor/github.com/klauspost/compress/compressible.go create mode 100644 vendor/github.com/klauspost/compress/fse/README.md create mode 100644 vendor/github.com/klauspost/compress/fse/bitreader.go create mode 100644 vendor/github.com/klauspost/compress/fse/bitwriter.go create mode 100644 vendor/github.com/klauspost/compress/fse/bytereader.go create mode 100644 vendor/github.com/klauspost/compress/fse/compress.go create mode 100644 vendor/github.com/klauspost/compress/fse/decompress.go create mode 100644 vendor/github.com/klauspost/compress/fse/fse.go create mode 100644 vendor/github.com/klauspost/compress/gen.sh create mode 100644 vendor/github.com/klauspost/compress/huff0/.gitignore create mode 100644 vendor/github.com/klauspost/compress/huff0/README.md create mode 100644 vendor/github.com/klauspost/compress/huff0/bitreader.go create mode 100644 vendor/github.com/klauspost/compress/huff0/bitwriter.go create mode 100644 vendor/github.com/klauspost/compress/huff0/bytereader.go create mode 100644 vendor/github.com/klauspost/compress/huff0/compress.go create mode 100644 vendor/github.com/klauspost/compress/huff0/decompress.go create mode 100644 vendor/github.com/klauspost/compress/huff0/decompress_amd64.go create mode 100644 vendor/github.com/klauspost/compress/huff0/decompress_amd64.s create mode 100644 vendor/github.com/klauspost/compress/huff0/decompress_generic.go create mode 100644 vendor/github.com/klauspost/compress/huff0/huff0.go create mode 100644 vendor/github.com/klauspost/compress/internal/cpuinfo/cpuinfo.go create mode 100644 vendor/github.com/klauspost/compress/internal/cpuinfo/cpuinfo_amd64.go create mode 100644 vendor/github.com/klauspost/compress/internal/cpuinfo/cpuinfo_amd64.s create mode 100644 vendor/github.com/klauspost/compress/internal/snapref/LICENSE create mode 100644 vendor/github.com/klauspost/compress/internal/snapref/decode.go create mode 100644 vendor/github.com/klauspost/compress/internal/snapref/decode_other.go create mode 100644 vendor/github.com/klauspost/compress/internal/snapref/encode.go create mode 100644 vendor/github.com/klauspost/compress/internal/snapref/encode_other.go create mode 100644 vendor/github.com/klauspost/compress/internal/snapref/snappy.go create mode 100644 vendor/github.com/klauspost/compress/s2sx.mod create mode 100644 vendor/github.com/klauspost/compress/s2sx.sum create mode 100644 vendor/github.com/klauspost/compress/zstd/README.md create mode 100644 vendor/github.com/klauspost/compress/zstd/bitreader.go create mode 100644 vendor/github.com/klauspost/compress/zstd/bitwriter.go create mode 100644 vendor/github.com/klauspost/compress/zstd/blockdec.go create mode 100644 vendor/github.com/klauspost/compress/zstd/blockenc.go create mode 100644 vendor/github.com/klauspost/compress/zstd/blocktype_string.go create mode 100644 vendor/github.com/klauspost/compress/zstd/bytebuf.go create mode 100644 vendor/github.com/klauspost/compress/zstd/bytereader.go create mode 100644 vendor/github.com/klauspost/compress/zstd/decodeheader.go create mode 100644 vendor/github.com/klauspost/compress/zstd/decoder.go create mode 100644 vendor/github.com/klauspost/compress/zstd/decoder_options.go create mode 100644 vendor/github.com/klauspost/compress/zstd/dict.go create mode 100644 vendor/github.com/klauspost/compress/zstd/enc_base.go create mode 100644 vendor/github.com/klauspost/compress/zstd/enc_best.go create mode 100644 vendor/github.com/klauspost/compress/zstd/enc_better.go create mode 100644 vendor/github.com/klauspost/compress/zstd/enc_dfast.go create mode 100644 vendor/github.com/klauspost/compress/zstd/enc_fast.go create mode 100644 vendor/github.com/klauspost/compress/zstd/encoder.go create mode 100644 vendor/github.com/klauspost/compress/zstd/encoder_options.go create mode 100644 vendor/github.com/klauspost/compress/zstd/framedec.go create mode 100644 vendor/github.com/klauspost/compress/zstd/frameenc.go create mode 100644 vendor/github.com/klauspost/compress/zstd/fse_decoder.go create mode 100644 vendor/github.com/klauspost/compress/zstd/fse_decoder_amd64.go create mode 100644 vendor/github.com/klauspost/compress/zstd/fse_decoder_amd64.s create mode 100644 vendor/github.com/klauspost/compress/zstd/fse_decoder_generic.go create mode 100644 vendor/github.com/klauspost/compress/zstd/fse_encoder.go create mode 100644 vendor/github.com/klauspost/compress/zstd/fse_predefined.go create mode 100644 vendor/github.com/klauspost/compress/zstd/hash.go create mode 100644 vendor/github.com/klauspost/compress/zstd/history.go create mode 100644 vendor/github.com/klauspost/compress/zstd/internal/xxhash/LICENSE.txt create mode 100644 vendor/github.com/klauspost/compress/zstd/internal/xxhash/README.md create mode 100644 vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash.go create mode 100644 vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_amd64.s create mode 100644 vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_arm64.s create mode 100644 vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_asm.go create mode 100644 vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_other.go create mode 100644 vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_safe.go create mode 100644 vendor/github.com/klauspost/compress/zstd/matchlen_amd64.go create mode 100644 vendor/github.com/klauspost/compress/zstd/matchlen_amd64.s create mode 100644 vendor/github.com/klauspost/compress/zstd/matchlen_generic.go create mode 100644 vendor/github.com/klauspost/compress/zstd/seqdec.go create mode 100644 vendor/github.com/klauspost/compress/zstd/seqdec_amd64.go create mode 100644 vendor/github.com/klauspost/compress/zstd/seqdec_amd64.s create mode 100644 vendor/github.com/klauspost/compress/zstd/seqdec_generic.go create mode 100644 vendor/github.com/klauspost/compress/zstd/seqenc.go create mode 100644 vendor/github.com/klauspost/compress/zstd/snappy.go create mode 100644 vendor/github.com/klauspost/compress/zstd/zip.go create mode 100644 vendor/github.com/klauspost/compress/zstd/zstd.go create mode 100644 vendor/github.com/klauspost/cpuid/v2/.gitignore create mode 100644 vendor/github.com/klauspost/cpuid/v2/.goreleaser.yml create mode 100644 vendor/github.com/klauspost/cpuid/v2/CONTRIBUTING.txt create mode 100644 vendor/github.com/klauspost/cpuid/v2/LICENSE create mode 100644 vendor/github.com/klauspost/cpuid/v2/README.md create mode 100644 vendor/github.com/klauspost/cpuid/v2/cpuid.go create mode 100644 vendor/github.com/klauspost/cpuid/v2/cpuid_386.s create mode 100644 vendor/github.com/klauspost/cpuid/v2/cpuid_amd64.s create mode 100644 vendor/github.com/klauspost/cpuid/v2/cpuid_arm64.s create mode 100644 vendor/github.com/klauspost/cpuid/v2/detect_arm64.go create mode 100644 vendor/github.com/klauspost/cpuid/v2/detect_ref.go create mode 100644 vendor/github.com/klauspost/cpuid/v2/detect_x86.go create mode 100644 vendor/github.com/klauspost/cpuid/v2/featureid_string.go create mode 100644 vendor/github.com/klauspost/cpuid/v2/os_darwin_arm64.go create mode 100644 vendor/github.com/klauspost/cpuid/v2/os_linux_arm64.go create mode 100644 vendor/github.com/klauspost/cpuid/v2/os_other_arm64.go create mode 100644 vendor/github.com/klauspost/cpuid/v2/os_safe_linux_arm64.go create mode 100644 vendor/github.com/klauspost/cpuid/v2/os_unsafe_linux_arm64.go create mode 100644 vendor/github.com/klauspost/cpuid/v2/test-architectures.sh create mode 100644 vendor/github.com/pierrec/lz4/v4/.gitignore create mode 100644 vendor/github.com/pierrec/lz4/v4/LICENSE create mode 100644 vendor/github.com/pierrec/lz4/v4/README.md create mode 100644 vendor/github.com/pierrec/lz4/v4/internal/lz4block/block.go create mode 100644 vendor/github.com/pierrec/lz4/v4/internal/lz4block/blocks.go create mode 100644 vendor/github.com/pierrec/lz4/v4/internal/lz4block/decode_amd64.s create mode 100644 vendor/github.com/pierrec/lz4/v4/internal/lz4block/decode_arm.s create mode 100644 vendor/github.com/pierrec/lz4/v4/internal/lz4block/decode_arm64.s create mode 100644 vendor/github.com/pierrec/lz4/v4/internal/lz4block/decode_asm.go create mode 100644 vendor/github.com/pierrec/lz4/v4/internal/lz4block/decode_other.go create mode 100644 vendor/github.com/pierrec/lz4/v4/internal/lz4errors/errors.go create mode 100644 vendor/github.com/pierrec/lz4/v4/internal/lz4stream/block.go create mode 100644 vendor/github.com/pierrec/lz4/v4/internal/lz4stream/frame.go create mode 100644 vendor/github.com/pierrec/lz4/v4/internal/lz4stream/frame_gen.go create mode 100644 vendor/github.com/pierrec/lz4/v4/internal/xxh32/xxh32zero.go create mode 100644 vendor/github.com/pierrec/lz4/v4/internal/xxh32/xxh32zero_arm.go create mode 100644 vendor/github.com/pierrec/lz4/v4/internal/xxh32/xxh32zero_arm.s create mode 100644 vendor/github.com/pierrec/lz4/v4/internal/xxh32/xxh32zero_other.go create mode 100644 vendor/github.com/pierrec/lz4/v4/lz4.go create mode 100644 vendor/github.com/pierrec/lz4/v4/options.go create mode 100644 vendor/github.com/pierrec/lz4/v4/options_gen.go create mode 100644 vendor/github.com/pierrec/lz4/v4/reader.go create mode 100644 vendor/github.com/pierrec/lz4/v4/state.go create mode 100644 vendor/github.com/pierrec/lz4/v4/state_gen.go create mode 100644 vendor/github.com/pierrec/lz4/v4/writer.go create mode 100644 vendor/github.com/zeebo/xxh3/.gitignore create mode 100644 vendor/github.com/zeebo/xxh3/LICENSE create mode 100644 vendor/github.com/zeebo/xxh3/Makefile create mode 100644 vendor/github.com/zeebo/xxh3/README.md create mode 100644 vendor/github.com/zeebo/xxh3/_compat.c create mode 100644 vendor/github.com/zeebo/xxh3/accum_generic.go create mode 100644 vendor/github.com/zeebo/xxh3/accum_stubs_amd64.go create mode 100644 vendor/github.com/zeebo/xxh3/accum_stubs_other.go create mode 100644 vendor/github.com/zeebo/xxh3/accum_vector_avx512_amd64.s create mode 100644 vendor/github.com/zeebo/xxh3/accum_vector_avx_amd64.s create mode 100644 vendor/github.com/zeebo/xxh3/accum_vector_sse_amd64.s create mode 100644 vendor/github.com/zeebo/xxh3/consts.go create mode 100644 vendor/github.com/zeebo/xxh3/hash128.go create mode 100644 vendor/github.com/zeebo/xxh3/hash128_seed.go create mode 100644 vendor/github.com/zeebo/xxh3/hash64.go create mode 100644 vendor/github.com/zeebo/xxh3/hash64_seed.go create mode 100644 vendor/github.com/zeebo/xxh3/hasher.go create mode 100644 vendor/github.com/zeebo/xxh3/utils.go (limited to 'vendor/github.com') diff --git a/vendor/github.com/apache/arrow/go/v14/LICENSE.txt b/vendor/github.com/apache/arrow/go/v14/LICENSE.txt new file mode 100644 index 000000000..573103298 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/LICENSE.txt @@ -0,0 +1,1791 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +-------------------------------------------------------------------------------- + +src/arrow/util (some portions): Apache 2.0, and 3-clause BSD + +Some portions of this module are derived from code in the Chromium project, +copyright (c) Google inc and (c) The Chromium Authors and licensed under the +Apache 2.0 License or the under the 3-clause BSD license: + + Copyright (c) 2013 The Chromium Authors. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +-------------------------------------------------------------------------------- + +This project includes code from Daniel Lemire's FrameOfReference project. + +https://github.com/lemire/FrameOfReference/blob/6ccaf9e97160f9a3b299e23a8ef739e711ef0c71/src/bpacking.cpp + +Copyright: 2013 Daniel Lemire +Home page: http://lemire.me/en/ +Project page: https://github.com/lemire/FrameOfReference +License: Apache License Version 2.0 http://www.apache.org/licenses/LICENSE-2.0 + +-------------------------------------------------------------------------------- + +This project includes code from the TensorFlow project + +Copyright 2015 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +-------------------------------------------------------------------------------- + +This project includes code from the NumPy project. + +https://github.com/numpy/numpy/blob/e1f191c46f2eebd6cb892a4bfe14d9dd43a06c4e/numpy/core/src/multiarray/multiarraymodule.c#L2910 + +https://github.com/numpy/numpy/blob/68fd82271b9ea5a9e50d4e761061dfcca851382a/numpy/core/src/multiarray/datetime.c + +Copyright (c) 2005-2017, NumPy Developers. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * Neither the name of the NumPy Developers nor the names of any + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +-------------------------------------------------------------------------------- + +This project includes code from the Boost project + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------------- + +This project includes code from the FlatBuffers project + +Copyright 2014 Google Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +-------------------------------------------------------------------------------- + +This project includes code from the tslib project + +Copyright 2015 Microsoft Corporation. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +-------------------------------------------------------------------------------- + +This project includes code from the jemalloc project + +https://github.com/jemalloc/jemalloc + +Copyright (C) 2002-2017 Jason Evans . +All rights reserved. +Copyright (C) 2007-2012 Mozilla Foundation. All rights reserved. +Copyright (C) 2009-2017 Facebook, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +1. Redistributions of source code must retain the above copyright notice(s), + this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice(s), + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY EXPRESS +OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +EVENT SHALL THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-------------------------------------------------------------------------------- + +This project includes code from the Go project, BSD 3-clause license + PATENTS +weak patent termination clause +(https://github.com/golang/go/blob/master/PATENTS). + +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +-------------------------------------------------------------------------------- + +This project includes code from the hs2client + +https://github.com/cloudera/hs2client + +Copyright 2016 Cloudera Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +-------------------------------------------------------------------------------- + +The script ci/scripts/util_wait_for_it.sh has the following license + +Copyright (c) 2016 Giles Hall + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +-------------------------------------------------------------------------------- + +The script r/configure has the following license (MIT) + +Copyright (c) 2017, Jeroen Ooms and Jim Hester + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +-------------------------------------------------------------------------------- + +cpp/src/arrow/util/logging.cc, cpp/src/arrow/util/logging.h and +cpp/src/arrow/util/logging-test.cc are adapted from +Ray Project (https://github.com/ray-project/ray) (Apache 2.0). + +Copyright (c) 2016 Ray Project (https://github.com/ray-project/ray) + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +-------------------------------------------------------------------------------- +The files cpp/src/arrow/vendored/datetime/date.h, cpp/src/arrow/vendored/datetime/tz.h, +cpp/src/arrow/vendored/datetime/tz_private.h, cpp/src/arrow/vendored/datetime/ios.h, +cpp/src/arrow/vendored/datetime/ios.mm, +cpp/src/arrow/vendored/datetime/tz.cpp are adapted from +Howard Hinnant's date library (https://github.com/HowardHinnant/date) +It is licensed under MIT license. + +The MIT License (MIT) +Copyright (c) 2015, 2016, 2017 Howard Hinnant +Copyright (c) 2016 Adrian Colomitchi +Copyright (c) 2017 Florian Dang +Copyright (c) 2017 Paul Thompson +Copyright (c) 2018 Tomasz Kamiński + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +-------------------------------------------------------------------------------- + +The file cpp/src/arrow/util/utf8.h includes code adapted from the page + https://bjoern.hoehrmann.de/utf-8/decoder/dfa/ +with the following license (MIT) + +Copyright (c) 2008-2009 Bjoern Hoehrmann + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +-------------------------------------------------------------------------------- + +The file cpp/src/arrow/vendored/string_view.hpp has the following license + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------------- + +The files in cpp/src/arrow/vendored/xxhash/ have the following license +(BSD 2-Clause License) + +xxHash Library +Copyright (c) 2012-2014, Yann Collet +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +You can contact the author at : +- xxHash homepage: http://www.xxhash.com +- xxHash source repository : https://github.com/Cyan4973/xxHash + +-------------------------------------------------------------------------------- + +The files in cpp/src/arrow/vendored/double-conversion/ have the following license +(BSD 3-Clause License) + +Copyright 2006-2011, the V8 project authors. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +-------------------------------------------------------------------------------- + +The files in cpp/src/arrow/vendored/uriparser/ have the following license +(BSD 3-Clause License) + +uriparser - RFC 3986 URI parsing library + +Copyright (C) 2007, Weijia Song +Copyright (C) 2007, Sebastian Pipping +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + * Neither the name of the nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +OF THE POSSIBILITY OF SUCH DAMAGE. + +-------------------------------------------------------------------------------- + +The files under dev/tasks/conda-recipes have the following license + +BSD 3-clause license +Copyright (c) 2015-2018, conda-forge +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +-------------------------------------------------------------------------------- + +The files in cpp/src/arrow/vendored/utf8cpp/ have the following license + +Copyright 2006 Nemanja Trifunovic + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------------- + +This project includes code from Apache Kudu. + + * cpp/cmake_modules/CompilerInfo.cmake is based on Kudu's cmake_modules/CompilerInfo.cmake + +Copyright: 2016 The Apache Software Foundation. +Home page: https://kudu.apache.org/ +License: http://www.apache.org/licenses/LICENSE-2.0 + +-------------------------------------------------------------------------------- + +This project includes code from Apache Impala (incubating), formerly +Impala. The Impala code and rights were donated to the ASF as part of the +Incubator process after the initial code imports into Apache Parquet. + +Copyright: 2012 Cloudera, Inc. +Copyright: 2016 The Apache Software Foundation. +Home page: http://impala.apache.org/ +License: http://www.apache.org/licenses/LICENSE-2.0 + +-------------------------------------------------------------------------------- + +This project includes code from Apache Aurora. + +* dev/release/{release,changelog,release-candidate} are based on the scripts from + Apache Aurora + +Copyright: 2016 The Apache Software Foundation. +Home page: https://aurora.apache.org/ +License: http://www.apache.org/licenses/LICENSE-2.0 + +-------------------------------------------------------------------------------- + +This project includes code from the Google styleguide. + +* cpp/build-support/cpplint.py is based on the scripts from the Google styleguide. + +Copyright: 2009 Google Inc. All rights reserved. +Homepage: https://github.com/google/styleguide +License: 3-clause BSD + +-------------------------------------------------------------------------------- + +This project includes code from Snappy. + +* cpp/cmake_modules/{SnappyCMakeLists.txt,SnappyConfig.h} are based on code + from Google's Snappy project. + +Copyright: 2009 Google Inc. All rights reserved. +Homepage: https://github.com/google/snappy +License: 3-clause BSD + +-------------------------------------------------------------------------------- + +This project includes code from the manylinux project. + +* python/manylinux1/scripts/{build_python.sh,python-tag-abi-tag.py, + requirements.txt} are based on code from the manylinux project. + +Copyright: 2016 manylinux +Homepage: https://github.com/pypa/manylinux +License: The MIT License (MIT) + +-------------------------------------------------------------------------------- + +This project includes code from the cymove project: + +* python/pyarrow/includes/common.pxd includes code from the cymove project + +The MIT License (MIT) +Copyright (c) 2019 Omer Ozarslan + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +OR OTHER DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------------- + +The projects includes code from the Ursabot project under the dev/archery +directory. + +License: BSD 2-Clause + +Copyright 2019 RStudio, Inc. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +-------------------------------------------------------------------------------- + +This project include code from CMake. + +* cpp/cmake_modules/FindGTest.cmake is based on code from CMake. + +Copyright: Copyright 2000-2019 Kitware, Inc. and Contributors +Homepage: https://gitlab.kitware.com/cmake/cmake +License: 3-clause BSD + +-------------------------------------------------------------------------------- + +This project include code from mingw-w64. + +* cpp/src/arrow/util/cpu-info.cc has a polyfill for mingw-w64 < 5 + +Copyright (c) 2009 - 2013 by the mingw-w64 project +Homepage: https://mingw-w64.org +License: Zope Public License (ZPL) Version 2.1. + +--------------------------------------------------------------------------------- + +This project include code from Google's Asylo project. + +* cpp/src/arrow/result.h is based on status_or.h + +Copyright (c) Copyright 2017 Asylo authors +Homepage: https://asylo.dev/ +License: Apache 2.0 + +-------------------------------------------------------------------------------- + +This project includes code from Google's protobuf project + +* cpp/src/arrow/result.h ARROW_ASSIGN_OR_RAISE is based off ASSIGN_OR_RETURN + +Copyright 2008 Google Inc. All rights reserved. +Homepage: https://developers.google.com/protocol-buffers/ +License: + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Code generated by the Protocol Buffer compiler is owned by the owner +of the input file used when generating it. This code is not +standalone and requires a support library to be linked with it. This +support library is itself covered by the above license. + +-------------------------------------------------------------------------------- + +3rdparty dependency LLVM is statically linked in certain binary distributions. +Additionally some sections of source code have been derived from sources in LLVM +and have been clearly labeled as such. LLVM has the following license: + +============================================================================== +LLVM Release License +============================================================================== +University of Illinois/NCSA +Open Source License + +Copyright (c) 2003-2018 University of Illinois at Urbana-Champaign. +All rights reserved. + +Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE +SOFTWARE. + +============================================================================== +Copyrights and Licenses for Third Party Software Distributed with LLVM: +============================================================================== +The LLVM software contains code written by third parties. Such software will +have its own individual LICENSE.TXT file in the directory in which it appears. +This file will describe the copyrights, license, and restrictions which apply +to that code. + +The disclaimer of warranty in the University of Illinois Open Source License +applies to all code in the LLVM Distribution, and nothing in any of the +other licenses gives permission to use the names of the LLVM Team or the +University of Illinois to endorse or promote products derived from this +Software. + +The following pieces of software have additional or alternate copyrights, +licenses, and/or restrictions: + +Program Directory +------- --------- +Google Test llvm/utils/unittest/googletest +OpenBSD regex llvm/lib/Support/{reg*, COPYRIGHT.regex} +pyyaml tests llvm/test/YAMLParser/{*.data, LICENSE.TXT} +ARM contributions llvm/lib/Target/ARM/LICENSE.TXT +md5 contributions llvm/lib/Support/MD5.cpp llvm/include/llvm/Support/MD5.h + +-------------------------------------------------------------------------------- + +3rdparty dependency gRPC is statically linked in certain binary +distributions, like the python wheels. gRPC has the following license: + +Copyright 2014 gRPC authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +-------------------------------------------------------------------------------- + +3rdparty dependency Apache Thrift is statically linked in certain binary +distributions, like the python wheels. Apache Thrift has the following license: + +Apache Thrift +Copyright (C) 2006 - 2019, The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +-------------------------------------------------------------------------------- + +3rdparty dependency Apache ORC is statically linked in certain binary +distributions, like the python wheels. Apache ORC has the following license: + +Apache ORC +Copyright 2013-2019 The Apache Software Foundation + +This product includes software developed by The Apache Software +Foundation (http://www.apache.org/). + +This product includes software developed by Hewlett-Packard: +(c) Copyright [2014-2015] Hewlett-Packard Development Company, L.P + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +-------------------------------------------------------------------------------- + +3rdparty dependency zstd is statically linked in certain binary +distributions, like the python wheels. ZSTD has the following license: + +BSD License + +For Zstandard software + +Copyright (c) 2016-present, Facebook, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name Facebook nor the names of its contributors may be used to + endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +-------------------------------------------------------------------------------- + +3rdparty dependency lz4 is statically linked in certain binary +distributions, like the python wheels. lz4 has the following license: + +LZ4 Library +Copyright (c) 2011-2016, Yann Collet +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +-------------------------------------------------------------------------------- + +3rdparty dependency Brotli is statically linked in certain binary +distributions, like the python wheels. Brotli has the following license: + +Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +-------------------------------------------------------------------------------- + +3rdparty dependency snappy is statically linked in certain binary +distributions, like the python wheels. snappy has the following license: + +Copyright 2011, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of Google Inc. nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=== + +Some of the benchmark data in testdata/ is licensed differently: + + - fireworks.jpeg is Copyright 2013 Steinar H. Gunderson, and + is licensed under the Creative Commons Attribution 3.0 license + (CC-BY-3.0). See https://creativecommons.org/licenses/by/3.0/ + for more information. + + - kppkn.gtb is taken from the Gaviota chess tablebase set, and + is licensed under the MIT License. See + https://sites.google.com/site/gaviotachessengine/Home/endgame-tablebases-1 + for more information. + + - paper-100k.pdf is an excerpt (bytes 92160 to 194560) from the paper + “Combinatorial Modeling of Chromatin Features Quantitatively Predicts DNA + Replication Timing in _Drosophila_” by Federico Comoglio and Renato Paro, + which is licensed under the CC-BY license. See + http://www.ploscompbiol.org/static/license for more ifnormation. + + - alice29.txt, asyoulik.txt, plrabn12.txt and lcet10.txt are from Project + Gutenberg. The first three have expired copyrights and are in the public + domain; the latter does not have expired copyright, but is still in the + public domain according to the license information + (http://www.gutenberg.org/ebooks/53). + +-------------------------------------------------------------------------------- + +3rdparty dependency gflags is statically linked in certain binary +distributions, like the python wheels. gflags has the following license: + +Copyright (c) 2006, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +-------------------------------------------------------------------------------- + +3rdparty dependency glog is statically linked in certain binary +distributions, like the python wheels. glog has the following license: + +Copyright (c) 2008, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +A function gettimeofday in utilities.cc is based on + +http://www.google.com/codesearch/p?hl=en#dR3YEbitojA/COPYING&q=GetSystemTimeAsFileTime%20license:bsd + +The license of this code is: + +Copyright (c) 2003-2008, Jouni Malinen and contributors +All Rights Reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name(s) of the above-listed copyright holder(s) nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +-------------------------------------------------------------------------------- + +3rdparty dependency re2 is statically linked in certain binary +distributions, like the python wheels. re2 has the following license: + +Copyright (c) 2009 The RE2 Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +-------------------------------------------------------------------------------- + +3rdparty dependency c-ares is statically linked in certain binary +distributions, like the python wheels. c-ares has the following license: + +# c-ares license + +Copyright (c) 2007 - 2018, Daniel Stenberg with many contributors, see AUTHORS +file. + +Copyright 1998 by the Massachusetts Institute of Technology. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, provided that +the above copyright notice appear in all copies and that both that copyright +notice and this permission notice appear in supporting documentation, and that +the name of M.I.T. not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior permission. +M.I.T. makes no representations about the suitability of this software for any +purpose. It is provided "as is" without express or implied warranty. + +-------------------------------------------------------------------------------- + +3rdparty dependency zlib is redistributed as a dynamically linked shared +library in certain binary distributions, like the python wheels. In the future +this will likely change to static linkage. zlib has the following license: + +zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.11, January 15th, 2017 + + Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + +-------------------------------------------------------------------------------- + +3rdparty dependency openssl is redistributed as a dynamically linked shared +library in certain binary distributions, like the python wheels. openssl +preceding version 3 has the following license: + + LICENSE ISSUES + ============== + + The OpenSSL toolkit stays under a double license, i.e. both the conditions of + the OpenSSL License and the original SSLeay license apply to the toolkit. + See below for the actual license texts. + + OpenSSL License + --------------- + +/* ==================================================================== + * Copyright (c) 1998-2019 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + + Original SSLeay License + ----------------------- + +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +-------------------------------------------------------------------------------- + +This project includes code from the rtools-backports project. + +* ci/scripts/PKGBUILD and ci/scripts/r_windows_build.sh are based on code + from the rtools-backports project. + +Copyright: Copyright (c) 2013 - 2019, Алексей and Jeroen Ooms. +All rights reserved. +Homepage: https://github.com/r-windows/rtools-backports +License: 3-clause BSD + +-------------------------------------------------------------------------------- + +Some code from pandas has been adapted for the pyarrow codebase. pandas is +available under the 3-clause BSD license, which follows: + +pandas license +============== + +Copyright (c) 2011-2012, Lambda Foundry, Inc. and PyData Development Team +All rights reserved. + +Copyright (c) 2008-2011 AQR Capital Management, LLC +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * Neither the name of the copyright holder nor the names of any + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +-------------------------------------------------------------------------------- + +Some bits from DyND, in particular aspects of the build system, have been +adapted from libdynd and dynd-python under the terms of the BSD 2-clause +license + +The BSD 2-Clause License + + Copyright (C) 2011-12, Dynamic NDArray Developers + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Dynamic NDArray Developers list: + + * Mark Wiebe + * Continuum Analytics + +-------------------------------------------------------------------------------- + +Some source code from Ibis (https://github.com/cloudera/ibis) has been adapted +for PyArrow. Ibis is released under the Apache License, Version 2.0. + +-------------------------------------------------------------------------------- + +dev/tasks/homebrew-formulae/apache-arrow.rb has the following license: + +BSD 2-Clause License + +Copyright (c) 2009-present, Homebrew contributors +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- + +cpp/src/arrow/vendored/base64.cpp has the following license + +ZLIB License + +Copyright (C) 2004-2017 René Nyffenegger + +This source code is provided 'as-is', without any express or implied +warranty. In no event will the author be held liable for any damages arising +from the use of this software. + +Permission is granted to anyone to use this software for any purpose, including +commercial applications, and to alter it and redistribute it freely, subject to +the following restrictions: + +1. The origin of this source code must not be misrepresented; you must not + claim that you wrote the original source code. If you use this source code + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original source code. + +3. This notice may not be removed or altered from any source distribution. + +René Nyffenegger rene.nyffenegger@adp-gmbh.ch + +-------------------------------------------------------------------------------- + +The file cpp/src/arrow/vendored/optional.hpp has the following license + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------------- + +The file cpp/src/arrow/vendored/musl/strptime.c has the following license + +Copyright © 2005-2020 Rich Felker, et al. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/.editorconfig b/vendor/github.com/apache/arrow/go/v14/arrow/.editorconfig new file mode 100644 index 000000000..a7ceaf938 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/.editorconfig @@ -0,0 +1,21 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +root = true + +[*.tmpl] +indent_style = tab +indent_size = 4 \ No newline at end of file diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/.gitignore b/vendor/github.com/apache/arrow/go/v14/arrow/.gitignore new file mode 100644 index 000000000..d4b831ae8 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/.gitignore @@ -0,0 +1,35 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +### Go template +# Binaries for programs and plugins +*.exe +*.dll +*.so +*.dylib +*.o + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 +.glide/ + +bin/ +vendor/ \ No newline at end of file diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/Gopkg.lock b/vendor/github.com/apache/arrow/go/v14/arrow/Gopkg.lock new file mode 100644 index 000000000..143e4f93b --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/Gopkg.lock @@ -0,0 +1,44 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + digest = "1:56c130d885a4aacae1dd9c7b71cfe39912c7ebc1ff7d2b46083c8812996dc43b" + name = "github.com/davecgh/go-spew" + packages = ["spew"] + pruneopts = "" + revision = "346938d642f2ec3594ed81d874461961cd0faa76" + version = "v1.1.0" + +[[projects]] + digest = "1:1d7e1867c49a6dd9856598ef7c3123604ea3daabf5b83f303ff457bcbc410b1d" + name = "github.com/pkg/errors" + packages = ["."] + pruneopts = "" + revision = "ba968bfe8b2f7e042a574c888954fccecfa385b4" + version = "v0.8.1" + +[[projects]] + digest = "1:256484dbbcd271f9ecebc6795b2df8cad4c458dd0f5fd82a8c2fa0c29f233411" + name = "github.com/pmezard/go-difflib" + packages = ["difflib"] + pruneopts = "" + revision = "792786c7400a136282c1664665ae0a8db921c6c2" + version = "v1.0.0" + +[[projects]] + digest = "1:2d0dc026c4aef5e2f3a0e06a4dabe268b840d8f63190cf6894e02134a03f52c5" + name = "github.com/stretchr/testify" + packages = ["assert"] + pruneopts = "" + revision = "b91bfb9ebec76498946beb6af7c0230c7cc7ba6c" + version = "v1.2.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + input-imports = [ + "github.com/pkg/errors", + "github.com/stretchr/testify/assert", + ] + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/Gopkg.toml b/vendor/github.com/apache/arrow/go/v14/arrow/Gopkg.toml new file mode 100644 index 000000000..b27807d69 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/Gopkg.toml @@ -0,0 +1,23 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +[[constraint]] + name = "github.com/stretchr/testify" + version = "1.2.0" + +[[constraint]] + name = "github.com/pkg/errors" + version = "0.8.1" \ No newline at end of file diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/Makefile b/vendor/github.com/apache/arrow/go/v14/arrow/Makefile new file mode 100644 index 000000000..9c4a23262 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/Makefile @@ -0,0 +1,54 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +GO_BUILD=go build +GO_GEN=go generate +GO_TEST?=go test +GOPATH=$(realpath ../../../../../..) + +GO_SOURCES := $(shell find . -path ./_lib -prune -o -name '*.go' -not -name '*_test.go') +ALL_SOURCES := $(shell find . -path ./_lib -prune -o -name '*.go' -name '*.s' -not -name '*_test.go') +SOURCES_NO_VENDOR := $(shell find . -path ./vendor -prune -o -name "*.go" -not -name '*_test.go' -print) + +.PHONEY: test bench assembly generate + +assembly: + @$(MAKE) -C memory assembly + @$(MAKE) -C math assembly + +generate: bin/tmpl + bin/tmpl -i -data=numeric.tmpldata type_traits_numeric.gen.go.tmpl type_traits_numeric.gen_test.go.tmpl array/numeric.gen.go.tmpl array/numericbuilder.gen_test.go.tmpl array/numericbuilder.gen.go.tmpl array/bufferbuilder_numeric.gen.go.tmpl + bin/tmpl -i -data=datatype_numeric.gen.go.tmpldata datatype_numeric.gen.go.tmpl + @$(MAKE) -C math generate + +fmt: $(SOURCES_NO_VENDOR) + goimports -w $^ + +bench: $(GO_SOURCES) | assembly + $(GO_TEST) $(GO_TEST_ARGS) -bench=. -run=- ./... + +bench-noasm: $(GO_SOURCES) + $(GO_TEST) $(GO_TEST_ARGS) -tags='noasm' -bench=. -run=- ./... + +test: $(GO_SOURCES) | assembly + $(GO_TEST) $(GO_TEST_ARGS) ./... + +test-noasm: $(GO_SOURCES) + $(GO_TEST) $(GO_TEST_ARGS) -tags='noasm' ./... + +bin/tmpl: _tools/tmpl/main.go + $(GO_BUILD) -o $@ ./_tools/tmpl + diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array.go b/vendor/github.com/apache/arrow/go/v14/arrow/array.go new file mode 100644 index 000000000..7622e7503 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array.go @@ -0,0 +1,127 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package arrow + +import ( + "fmt" + + "github.com/apache/arrow/go/v14/arrow/memory" + "github.com/apache/arrow/go/v14/internal/json" +) + +// ArrayData is the underlying memory and metadata of an Arrow array, corresponding +// to the same-named object in the C++ implementation. +// +// The Array interface and subsequent typed objects provide strongly typed +// accessors which support marshalling and other patterns to the data. +// This interface allows direct access to the underlying raw byte buffers +// which allows for manipulating the internal data and casting. For example, +// one could cast the raw bytes from int64 to float64 like so: +// +// arrdata := GetMyInt64Data().Data() +// newdata := array.NewData(arrow.PrimitiveTypes.Float64, arrdata.Len(), +// arrdata.Buffers(), nil, arrdata.NullN(), arrdata.Offset()) +// defer newdata.Release() +// float64arr := array.NewFloat64Data(newdata) +// defer float64arr.Release() +// +// This is also useful in an analytics setting where memory may be reused. For +// example, if we had a group of operations all returning float64 such as: +// +// Log(Sqrt(Expr(arr))) +// +// The low-level implementations could have signatures such as: +// +// func Log(values arrow.ArrayData) arrow.ArrayData +// +// Another example would be a function that consumes one or more memory buffers +// in an input array and replaces them with newly-allocated data, changing the +// output data type as well. +type ArrayData interface { + // Retain increases the reference count by 1, it is safe to call + // in multiple goroutines simultaneously. + Retain() + // Release decreases the reference count by 1, it is safe to call + // in multiple goroutines simultaneously. Data is removed when reference + // count is 0. + Release() + // DataType returns the current datatype stored in the object. + DataType() DataType + // NullN returns the number of nulls for this data instance. + NullN() int + // Len returns the length of this data instance + Len() int + // Offset returns the offset into the raw buffers where this data begins + Offset() int + // Buffers returns the slice of raw data buffers for this data instance. Their + // meaning depends on the context of the data type. + Buffers() []*memory.Buffer + // Children returns the slice of children data instances, only relevant for + // nested data types. For instance, List data will have a single child containing + // elements of all the rows and Struct data will contain numfields children which + // are the arrays for each field of the struct. + Children() []ArrayData + // Reset allows reusing this ArrayData object by replacing the data in this ArrayData + // object without changing the reference count. + Reset(newtype DataType, newlength int, newbuffers []*memory.Buffer, newchildren []ArrayData, newnulls int, newoffset int) + // Dictionary returns the ArrayData object for the dictionary if this is a + // dictionary array, otherwise it will be nil. + Dictionary() ArrayData +} + +// Array represents an immutable sequence of values using the Arrow in-memory format. +type Array interface { + json.Marshaler + + fmt.Stringer + + // DataType returns the type metadata for this instance. + DataType() DataType + + // NullN returns the number of null values in the array. + NullN() int + + // NullBitmapBytes returns a byte slice of the validity bitmap. + NullBitmapBytes() []byte + + // IsNull returns true if value at index is null. + // NOTE: IsNull will panic if NullBitmapBytes is not empty and 0 > i ≥ Len. + IsNull(i int) bool + + // IsValid returns true if value at index is not null. + // NOTE: IsValid will panic if NullBitmapBytes is not empty and 0 > i ≥ Len. + IsValid(i int) bool + // ValueStr returns the value at index as a string. + ValueStr(i int) string + + // Get single value to be marshalled with `json.Marshal` + GetOneForMarshal(i int) interface{} + + Data() ArrayData + + // Len returns the number of elements in the array. + Len() int + + // Retain increases the reference count by 1. + // Retain may be called simultaneously from multiple goroutines. + Retain() + + // Release decreases the reference count by 1. + // Release may be called simultaneously from multiple goroutines. + // When the reference count goes to zero, the memory is freed. + Release() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array/array.go b/vendor/github.com/apache/arrow/go/v14/arrow/array/array.go new file mode 100644 index 000000000..1ee04c7aa --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array/array.go @@ -0,0 +1,185 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package array + +import ( + "sync/atomic" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/bitutil" + "github.com/apache/arrow/go/v14/arrow/internal/debug" +) + +const ( + // UnknownNullCount specifies the NullN should be calculated from the null bitmap buffer. + UnknownNullCount = -1 + + // NullValueStr represents a null value in arrow.Array.ValueStr and in Builder.AppendValueFromString. + // It should be returned from the arrow.Array.ValueStr implementations. + // Using it as the value in Builder.AppendValueFromString should be equivalent to Builder.AppendNull. + NullValueStr = "(null)" +) + +type array struct { + refCount int64 + data *Data + nullBitmapBytes []byte +} + +// Retain increases the reference count by 1. +// Retain may be called simultaneously from multiple goroutines. +func (a *array) Retain() { + atomic.AddInt64(&a.refCount, 1) +} + +// Release decreases the reference count by 1. +// Release may be called simultaneously from multiple goroutines. +// When the reference count goes to zero, the memory is freed. +func (a *array) Release() { + debug.Assert(atomic.LoadInt64(&a.refCount) > 0, "too many releases") + + if atomic.AddInt64(&a.refCount, -1) == 0 { + a.data.Release() + a.data, a.nullBitmapBytes = nil, nil + } +} + +// DataType returns the type metadata for this instance. +func (a *array) DataType() arrow.DataType { return a.data.dtype } + +// NullN returns the number of null values in the array. +func (a *array) NullN() int { + if a.data.nulls < 0 { + a.data.nulls = a.data.length - bitutil.CountSetBits(a.nullBitmapBytes, a.data.offset, a.data.length) + } + return a.data.nulls +} + +// NullBitmapBytes returns a byte slice of the validity bitmap. +func (a *array) NullBitmapBytes() []byte { return a.nullBitmapBytes } + +func (a *array) Data() arrow.ArrayData { return a.data } + +// Len returns the number of elements in the array. +func (a *array) Len() int { return a.data.length } + +// IsNull returns true if value at index is null. +// NOTE: IsNull will panic if NullBitmapBytes is not empty and 0 > i ≥ Len. +func (a *array) IsNull(i int) bool { + return len(a.nullBitmapBytes) != 0 && bitutil.BitIsNotSet(a.nullBitmapBytes, a.data.offset+i) +} + +// IsValid returns true if value at index is not null. +// NOTE: IsValid will panic if NullBitmapBytes is not empty and 0 > i ≥ Len. +func (a *array) IsValid(i int) bool { + return len(a.nullBitmapBytes) == 0 || bitutil.BitIsSet(a.nullBitmapBytes, a.data.offset+i) +} + +func (a *array) setData(data *Data) { + // Retain before releasing in case a.data is the same as data. + data.Retain() + + if a.data != nil { + a.data.Release() + } + + if len(data.buffers) > 0 && data.buffers[0] != nil { + a.nullBitmapBytes = data.buffers[0].Bytes() + } + a.data = data +} + +func (a *array) Offset() int { + return a.data.Offset() +} + +type arrayConstructorFn func(arrow.ArrayData) arrow.Array + +var ( + makeArrayFn [64]arrayConstructorFn +) + +func invalidDataType(data arrow.ArrayData) arrow.Array { + panic("invalid data type: " + data.DataType().ID().String()) +} + +// MakeFromData constructs a strongly-typed array instance from generic Data. +func MakeFromData(data arrow.ArrayData) arrow.Array { + return makeArrayFn[byte(data.DataType().ID()&0x3f)](data) +} + +// NewSlice constructs a zero-copy slice of the array with the indicated +// indices i and j, corresponding to array[i:j]. +// The returned array must be Release()'d after use. +// +// NewSlice panics if the slice is outside the valid range of the input array. +// NewSlice panics if j < i. +func NewSlice(arr arrow.Array, i, j int64) arrow.Array { + data := NewSliceData(arr.Data(), i, j) + slice := MakeFromData(data) + data.Release() + return slice +} + +func init() { + makeArrayFn = [...]arrayConstructorFn{ + arrow.NULL: func(data arrow.ArrayData) arrow.Array { return NewNullData(data) }, + arrow.BOOL: func(data arrow.ArrayData) arrow.Array { return NewBooleanData(data) }, + arrow.UINT8: func(data arrow.ArrayData) arrow.Array { return NewUint8Data(data) }, + arrow.INT8: func(data arrow.ArrayData) arrow.Array { return NewInt8Data(data) }, + arrow.UINT16: func(data arrow.ArrayData) arrow.Array { return NewUint16Data(data) }, + arrow.INT16: func(data arrow.ArrayData) arrow.Array { return NewInt16Data(data) }, + arrow.UINT32: func(data arrow.ArrayData) arrow.Array { return NewUint32Data(data) }, + arrow.INT32: func(data arrow.ArrayData) arrow.Array { return NewInt32Data(data) }, + arrow.UINT64: func(data arrow.ArrayData) arrow.Array { return NewUint64Data(data) }, + arrow.INT64: func(data arrow.ArrayData) arrow.Array { return NewInt64Data(data) }, + arrow.FLOAT16: func(data arrow.ArrayData) arrow.Array { return NewFloat16Data(data) }, + arrow.FLOAT32: func(data arrow.ArrayData) arrow.Array { return NewFloat32Data(data) }, + arrow.FLOAT64: func(data arrow.ArrayData) arrow.Array { return NewFloat64Data(data) }, + arrow.STRING: func(data arrow.ArrayData) arrow.Array { return NewStringData(data) }, + arrow.BINARY: func(data arrow.ArrayData) arrow.Array { return NewBinaryData(data) }, + arrow.FIXED_SIZE_BINARY: func(data arrow.ArrayData) arrow.Array { return NewFixedSizeBinaryData(data) }, + arrow.DATE32: func(data arrow.ArrayData) arrow.Array { return NewDate32Data(data) }, + arrow.DATE64: func(data arrow.ArrayData) arrow.Array { return NewDate64Data(data) }, + arrow.TIMESTAMP: func(data arrow.ArrayData) arrow.Array { return NewTimestampData(data) }, + arrow.TIME32: func(data arrow.ArrayData) arrow.Array { return NewTime32Data(data) }, + arrow.TIME64: func(data arrow.ArrayData) arrow.Array { return NewTime64Data(data) }, + arrow.INTERVAL_MONTHS: func(data arrow.ArrayData) arrow.Array { return NewMonthIntervalData(data) }, + arrow.INTERVAL_DAY_TIME: func(data arrow.ArrayData) arrow.Array { return NewDayTimeIntervalData(data) }, + arrow.DECIMAL128: func(data arrow.ArrayData) arrow.Array { return NewDecimal128Data(data) }, + arrow.DECIMAL256: func(data arrow.ArrayData) arrow.Array { return NewDecimal256Data(data) }, + arrow.LIST: func(data arrow.ArrayData) arrow.Array { return NewListData(data) }, + arrow.STRUCT: func(data arrow.ArrayData) arrow.Array { return NewStructData(data) }, + arrow.SPARSE_UNION: func(data arrow.ArrayData) arrow.Array { return NewSparseUnionData(data) }, + arrow.DENSE_UNION: func(data arrow.ArrayData) arrow.Array { return NewDenseUnionData(data) }, + arrow.DICTIONARY: func(data arrow.ArrayData) arrow.Array { return NewDictionaryData(data) }, + arrow.MAP: func(data arrow.ArrayData) arrow.Array { return NewMapData(data) }, + arrow.EXTENSION: func(data arrow.ArrayData) arrow.Array { return NewExtensionData(data) }, + arrow.FIXED_SIZE_LIST: func(data arrow.ArrayData) arrow.Array { return NewFixedSizeListData(data) }, + arrow.DURATION: func(data arrow.ArrayData) arrow.Array { return NewDurationData(data) }, + arrow.LARGE_STRING: func(data arrow.ArrayData) arrow.Array { return NewLargeStringData(data) }, + arrow.LARGE_BINARY: func(data arrow.ArrayData) arrow.Array { return NewLargeBinaryData(data) }, + arrow.LARGE_LIST: func(data arrow.ArrayData) arrow.Array { return NewLargeListData(data) }, + arrow.INTERVAL_MONTH_DAY_NANO: func(data arrow.ArrayData) arrow.Array { return NewMonthDayNanoIntervalData(data) }, + arrow.RUN_END_ENCODED: func(data arrow.ArrayData) arrow.Array { return NewRunEndEncodedData(data) }, + arrow.LIST_VIEW: func(data arrow.ArrayData) arrow.Array { return NewListViewData(data) }, + arrow.LARGE_LIST_VIEW: func(data arrow.ArrayData) arrow.Array { return NewLargeListViewData(data) }, + + // invalid data types to fill out array to size 2^6 - 1 + 63: invalidDataType, + } +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array/binary.go b/vendor/github.com/apache/arrow/go/v14/arrow/array/binary.go new file mode 100644 index 000000000..e9e6e66e7 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array/binary.go @@ -0,0 +1,323 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package array + +import ( + "bytes" + "encoding/base64" + "fmt" + "strings" + "unsafe" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/internal/json" +) + +type BinaryLike interface { + arrow.Array + ValueBytes() []byte + ValueOffset64(int) int64 +} + +// A type which represents an immutable sequence of variable-length binary strings. +type Binary struct { + array + valueOffsets []int32 + valueBytes []byte +} + +// NewBinaryData constructs a new Binary array from data. +func NewBinaryData(data arrow.ArrayData) *Binary { + a := &Binary{} + a.refCount = 1 + a.setData(data.(*Data)) + return a +} + +// Value returns the slice at index i. This value should not be mutated. +func (a *Binary) Value(i int) []byte { + if i < 0 || i >= a.array.data.length { + panic("arrow/array: index out of range") + } + idx := a.array.data.offset + i + return a.valueBytes[a.valueOffsets[idx]:a.valueOffsets[idx+1]] +} + +// ValueStr returns a copy of the base64-encoded string value or NullValueStr +func (a *Binary) ValueStr(i int) string { + if a.IsNull(i) { + return NullValueStr + } + return base64.StdEncoding.EncodeToString(a.Value(i)) +} + +// ValueString returns the string at index i without performing additional allocations. +// The string is only valid for the lifetime of the Binary array. +func (a *Binary) ValueString(i int) string { + b := a.Value(i) + return *(*string)(unsafe.Pointer(&b)) +} + +func (a *Binary) ValueOffset(i int) int { + if i < 0 || i >= a.array.data.length { + panic("arrow/array: index out of range") + } + return int(a.valueOffsets[a.array.data.offset+i]) +} + +func (a *Binary) ValueOffset64(i int) int64 { + return int64(a.ValueOffset(i)) +} + +func (a *Binary) ValueLen(i int) int { + if i < 0 || i >= a.array.data.length { + panic("arrow/array: index out of range") + } + beg := a.array.data.offset + i + return int(a.valueOffsets[beg+1] - a.valueOffsets[beg]) +} + +func (a *Binary) ValueOffsets() []int32 { + beg := a.array.data.offset + end := beg + a.array.data.length + 1 + return a.valueOffsets[beg:end] +} + +func (a *Binary) ValueBytes() []byte { + beg := a.array.data.offset + end := beg + a.array.data.length + return a.valueBytes[a.valueOffsets[beg]:a.valueOffsets[end]] +} + +func (a *Binary) String() string { + o := new(strings.Builder) + o.WriteString("[") + for i := 0; i < a.Len(); i++ { + if i > 0 { + o.WriteString(" ") + } + switch { + case a.IsNull(i): + o.WriteString(NullValueStr) + default: + fmt.Fprintf(o, "%q", a.ValueString(i)) + } + } + o.WriteString("]") + return o.String() +} + +func (a *Binary) setData(data *Data) { + if len(data.buffers) != 3 { + panic("len(data.buffers) != 3") + } + + a.array.setData(data) + + if valueData := data.buffers[2]; valueData != nil { + a.valueBytes = valueData.Bytes() + } + + if valueOffsets := data.buffers[1]; valueOffsets != nil { + a.valueOffsets = arrow.Int32Traits.CastFromBytes(valueOffsets.Bytes()) + } + + if a.array.data.length < 1 { + return + } + + expNumOffsets := a.array.data.offset + a.array.data.length + 1 + if len(a.valueOffsets) < expNumOffsets { + panic(fmt.Errorf("arrow/array: binary offset buffer must have at least %d values", expNumOffsets)) + } + + if int(a.valueOffsets[expNumOffsets-1]) > len(a.valueBytes) { + panic("arrow/array: binary offsets out of bounds of data buffer") + } +} + +func (a *Binary) GetOneForMarshal(i int) interface{} { + if a.IsNull(i) { + return nil + } + return a.Value(i) +} + +func (a *Binary) MarshalJSON() ([]byte, error) { + vals := make([]interface{}, a.Len()) + for i := 0; i < a.Len(); i++ { + vals[i] = a.GetOneForMarshal(i) + } + // golang marshal standard says that []byte will be marshalled + // as a base64-encoded string + return json.Marshal(vals) +} + +func arrayEqualBinary(left, right *Binary) bool { + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + if !bytes.Equal(left.Value(i), right.Value(i)) { + return false + } + } + return true +} + +type LargeBinary struct { + array + valueOffsets []int64 + valueBytes []byte +} + +func NewLargeBinaryData(data arrow.ArrayData) *LargeBinary { + a := &LargeBinary{} + a.refCount = 1 + a.setData(data.(*Data)) + return a +} + +func (a *LargeBinary) Value(i int) []byte { + if i < 0 || i >= a.array.data.length { + panic("arrow/array: index out of range") + } + idx := a.array.data.offset + i + return a.valueBytes[a.valueOffsets[idx]:a.valueOffsets[idx+1]] +} + +func (a *LargeBinary) ValueStr(i int) string { + if a.IsNull(i) { + return NullValueStr + } + return base64.StdEncoding.EncodeToString(a.Value(i)) +} +func (a *LargeBinary) ValueString(i int) string { + b := a.Value(i) + return *(*string)(unsafe.Pointer(&b)) +} + +func (a *LargeBinary) ValueOffset(i int) int64 { + if i < 0 || i >= a.array.data.length { + panic("arrow/array: index out of range") + } + return a.valueOffsets[a.array.data.offset+i] +} + +func (a *LargeBinary) ValueOffset64(i int) int64 { + return a.ValueOffset(i) +} + +func (a *LargeBinary) ValueLen(i int) int { + if i < 0 || i >= a.array.data.length { + panic("arrow/array: index out of range") + } + beg := a.array.data.offset + i + return int(a.valueOffsets[beg+1] - a.valueOffsets[beg]) +} + +func (a *LargeBinary) ValueOffsets() []int64 { + beg := a.array.data.offset + end := beg + a.array.data.length + 1 + return a.valueOffsets[beg:end] +} + +func (a *LargeBinary) ValueBytes() []byte { + beg := a.array.data.offset + end := beg + a.array.data.length + return a.valueBytes[a.valueOffsets[beg]:a.valueOffsets[end]] +} + +func (a *LargeBinary) String() string { + var o strings.Builder + o.WriteString("[") + for i := 0; i < a.Len(); i++ { + if i > 0 { + o.WriteString(" ") + } + switch { + case a.IsNull(i): + o.WriteString(NullValueStr) + default: + fmt.Fprintf(&o, "%q", a.ValueString(i)) + } + } + o.WriteString("]") + return o.String() +} + +func (a *LargeBinary) setData(data *Data) { + if len(data.buffers) != 3 { + panic("len(data.buffers) != 3") + } + + a.array.setData(data) + + if valueData := data.buffers[2]; valueData != nil { + a.valueBytes = valueData.Bytes() + } + + if valueOffsets := data.buffers[1]; valueOffsets != nil { + a.valueOffsets = arrow.Int64Traits.CastFromBytes(valueOffsets.Bytes()) + } + + if a.array.data.length < 1 { + return + } + + expNumOffsets := a.array.data.offset + a.array.data.length + 1 + if len(a.valueOffsets) < expNumOffsets { + panic(fmt.Errorf("arrow/array: large binary offset buffer must have at least %d values", expNumOffsets)) + } + + if int(a.valueOffsets[expNumOffsets-1]) > len(a.valueBytes) { + panic("arrow/array: large binary offsets out of bounds of data buffer") + } +} + +func (a *LargeBinary) GetOneForMarshal(i int) interface{} { + if a.IsNull(i) { + return nil + } + return a.Value(i) +} + +func (a *LargeBinary) MarshalJSON() ([]byte, error) { + vals := make([]interface{}, a.Len()) + for i := 0; i < a.Len(); i++ { + vals[i] = a.GetOneForMarshal(i) + } + // golang marshal standard says that []byte will be marshalled + // as a base64-encoded string + return json.Marshal(vals) +} + +func arrayEqualLargeBinary(left, right *LargeBinary) bool { + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + if !bytes.Equal(left.Value(i), right.Value(i)) { + return false + } + } + return true +} + +var ( + _ arrow.Array = (*Binary)(nil) +) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array/binarybuilder.go b/vendor/github.com/apache/arrow/go/v14/arrow/array/binarybuilder.go new file mode 100644 index 000000000..3cb709b45 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array/binarybuilder.go @@ -0,0 +1,375 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package array + +import ( + "bytes" + "encoding/base64" + "fmt" + "math" + "reflect" + "sync/atomic" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/internal/debug" + "github.com/apache/arrow/go/v14/arrow/memory" + "github.com/apache/arrow/go/v14/internal/json" +) + +// A BinaryBuilder is used to build a Binary array using the Append methods. +type BinaryBuilder struct { + builder + + dtype arrow.BinaryDataType + offsets bufBuilder + values *byteBufferBuilder + + appendOffsetVal func(int) + getOffsetVal func(int) int + maxCapacity uint64 + offsetByteWidth int +} + +// NewBinaryBuilder can be used for any of the variable length binary types, +// Binary, LargeBinary, String, LargeString by passing the appropriate data type +func NewBinaryBuilder(mem memory.Allocator, dtype arrow.BinaryDataType) *BinaryBuilder { + var ( + offsets bufBuilder + offsetValFn func(int) + maxCapacity uint64 + offsetByteWidth int + getOffsetVal func(int) int + ) + switch dtype.Layout().Buffers[1].ByteWidth { + case 4: + b := newInt32BufferBuilder(mem) + offsetValFn = func(v int) { b.AppendValue(int32(v)) } + getOffsetVal = func(i int) int { return int(b.Value(i)) } + offsets = b + maxCapacity = math.MaxInt32 + offsetByteWidth = arrow.Int32SizeBytes + case 8: + b := newInt64BufferBuilder(mem) + offsetValFn = func(v int) { b.AppendValue(int64(v)) } + getOffsetVal = func(i int) int { return int(b.Value(i)) } + offsets = b + maxCapacity = math.MaxInt64 + offsetByteWidth = arrow.Int64SizeBytes + } + + b := &BinaryBuilder{ + builder: builder{refCount: 1, mem: mem}, + dtype: dtype, + offsets: offsets, + values: newByteBufferBuilder(mem), + appendOffsetVal: offsetValFn, + maxCapacity: maxCapacity, + offsetByteWidth: offsetByteWidth, + getOffsetVal: getOffsetVal, + } + return b +} + +func (b *BinaryBuilder) Type() arrow.DataType { return b.dtype } + +// Release decreases the reference count by 1. +// When the reference count goes to zero, the memory is freed. +// Release may be called simultaneously from multiple goroutines. +func (b *BinaryBuilder) Release() { + debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases") + + if atomic.AddInt64(&b.refCount, -1) == 0 { + if b.nullBitmap != nil { + b.nullBitmap.Release() + b.nullBitmap = nil + } + if b.offsets != nil { + b.offsets.Release() + b.offsets = nil + } + if b.values != nil { + b.values.Release() + b.values = nil + } + } +} + +func (b *BinaryBuilder) Append(v []byte) { + b.Reserve(1) + b.appendNextOffset() + b.values.Append(v) + b.UnsafeAppendBoolToBitmap(true) +} + +func (b *BinaryBuilder) AppendString(v string) { + b.Append([]byte(v)) +} + +func (b *BinaryBuilder) AppendNull() { + b.Reserve(1) + b.appendNextOffset() + b.UnsafeAppendBoolToBitmap(false) +} + +func (b *BinaryBuilder) AppendNulls(n int) { + for i := 0; i < n; i++ { + b.AppendNull() + } +} + +func (b *BinaryBuilder) AppendEmptyValue() { + b.Reserve(1) + b.appendNextOffset() + b.UnsafeAppendBoolToBitmap(true) +} + +func (b *BinaryBuilder) AppendEmptyValues(n int) { + for i := 0; i < n; i++ { + b.AppendEmptyValue() + } +} + +// AppendValues will append the values in the v slice. The valid slice determines which values +// in v are valid (not null). The valid slice must either be empty or be equal in length to v. If empty, +// all values in v are appended and considered valid. +func (b *BinaryBuilder) AppendValues(v [][]byte, valid []bool) { + if len(v) != len(valid) && len(valid) != 0 { + panic("len(v) != len(valid) && len(valid) != 0") + } + + if len(v) == 0 { + return + } + + b.Reserve(len(v)) + for _, vv := range v { + b.appendNextOffset() + b.values.Append(vv) + } + + b.builder.unsafeAppendBoolsToBitmap(valid, len(v)) +} + +// AppendStringValues will append the values in the v slice. The valid slice determines which values +// in v are valid (not null). The valid slice must either be empty or be equal in length to v. If empty, +// all values in v are appended and considered valid. +func (b *BinaryBuilder) AppendStringValues(v []string, valid []bool) { + if len(v) != len(valid) && len(valid) != 0 { + panic("len(v) != len(valid) && len(valid) != 0") + } + + if len(v) == 0 { + return + } + + b.Reserve(len(v)) + for _, vv := range v { + b.appendNextOffset() + b.values.Append([]byte(vv)) + } + + b.builder.unsafeAppendBoolsToBitmap(valid, len(v)) +} + +func (b *BinaryBuilder) UnsafeAppend(v []byte) { + b.appendNextOffset() + b.values.unsafeAppend(v) + b.UnsafeAppendBoolToBitmap(true) +} + +func (b *BinaryBuilder) Value(i int) []byte { + start := b.getOffsetVal(i) + var end int + if i == (b.length - 1) { + end = b.values.Len() + } else { + end = b.getOffsetVal(i + 1) + } + return b.values.Bytes()[start:end] +} + +func (b *BinaryBuilder) init(capacity int) { + b.builder.init(capacity) + b.offsets.resize((capacity + 1) * b.offsetByteWidth) +} + +// DataLen returns the number of bytes in the data array. +func (b *BinaryBuilder) DataLen() int { return b.values.length } + +// DataCap returns the total number of bytes that can be stored +// without allocating additional memory. +func (b *BinaryBuilder) DataCap() int { return b.values.capacity } + +// Reserve ensures there is enough space for appending n elements +// by checking the capacity and calling Resize if necessary. +func (b *BinaryBuilder) Reserve(n int) { + b.builder.reserve(n, b.Resize) +} + +// ReserveData ensures there is enough space for appending n bytes +// by checking the capacity and resizing the data buffer if necessary. +func (b *BinaryBuilder) ReserveData(n int) { + if b.values.capacity < b.values.length+n { + b.values.resize(b.values.Len() + n) + } +} + +// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(), +// additional memory will be allocated. If n is smaller, the allocated memory may be reduced. +func (b *BinaryBuilder) Resize(n int) { + b.offsets.resize((n + 1) * b.offsetByteWidth) + if (n * b.offsetByteWidth) < b.offsets.Len() { + b.offsets.SetLength(n * b.offsetByteWidth) + } + b.builder.resize(n, b.init) +} + +func (b *BinaryBuilder) ResizeData(n int) { + b.values.length = n +} + +// NewArray creates a Binary array from the memory buffers used by the builder and resets the BinaryBuilder +// so it can be used to build a new array. +// +// Builds the appropriate Binary or LargeBinary array based on the datatype +// it was initialized with. +func (b *BinaryBuilder) NewArray() arrow.Array { + if b.offsetByteWidth == arrow.Int32SizeBytes { + return b.NewBinaryArray() + } + return b.NewLargeBinaryArray() +} + +// NewBinaryArray creates a Binary array from the memory buffers used by the builder and resets the BinaryBuilder +// so it can be used to build a new array. +func (b *BinaryBuilder) NewBinaryArray() (a *Binary) { + if b.offsetByteWidth != arrow.Int32SizeBytes { + panic("arrow/array: invalid call to NewBinaryArray when building a LargeBinary array") + } + + data := b.newData() + a = NewBinaryData(data) + data.Release() + return +} + +func (b *BinaryBuilder) NewLargeBinaryArray() (a *LargeBinary) { + if b.offsetByteWidth != arrow.Int64SizeBytes { + panic("arrow/array: invalid call to NewLargeBinaryArray when building a Binary array") + } + + data := b.newData() + a = NewLargeBinaryData(data) + data.Release() + return +} + +func (b *BinaryBuilder) newData() (data *Data) { + b.appendNextOffset() + offsets, values := b.offsets.Finish(), b.values.Finish() + data = NewData(b.dtype, b.length, []*memory.Buffer{b.nullBitmap, offsets, values}, nil, b.nulls, 0) + if offsets != nil { + offsets.Release() + } + + if values != nil { + values.Release() + } + + b.builder.reset() + + return +} + +func (b *BinaryBuilder) appendNextOffset() { + numBytes := b.values.Len() + debug.Assert(uint64(numBytes) <= b.maxCapacity, "exceeded maximum capacity of binary array") + b.appendOffsetVal(numBytes) +} + +func (b *BinaryBuilder) AppendValueFromString(s string) error { + if s == NullValueStr { + b.AppendNull() + return nil + } + + if b.dtype.IsUtf8() { + b.Append([]byte(s)) + return nil + } + + decodedVal, err := base64.StdEncoding.DecodeString(s) + if err != nil { + return fmt.Errorf("could not decode base64 string: %w", err) + } + b.Append(decodedVal) + return nil +} + +func (b *BinaryBuilder) UnmarshalOne(dec *json.Decoder) error { + t, err := dec.Token() + if err != nil { + return err + } + + switch v := t.(type) { + case string: + data, err := base64.StdEncoding.DecodeString(v) + if err != nil { + return err + } + b.Append(data) + case []byte: + b.Append(v) + case nil: + b.AppendNull() + default: + return &json.UnmarshalTypeError{ + Value: fmt.Sprint(t), + Type: reflect.TypeOf([]byte{}), + Offset: dec.InputOffset(), + } + } + return nil +} + +func (b *BinaryBuilder) Unmarshal(dec *json.Decoder) error { + for dec.More() { + if err := b.UnmarshalOne(dec); err != nil { + return err + } + } + return nil +} + +func (b *BinaryBuilder) UnmarshalJSON(data []byte) error { + dec := json.NewDecoder(bytes.NewReader(data)) + t, err := dec.Token() + if err != nil { + return err + } + + if delim, ok := t.(json.Delim); !ok || delim != '[' { + return fmt.Errorf("binary builder must unpack from json array, found %s", delim) + } + + return b.Unmarshal(dec) +} + +var ( + _ Builder = (*BinaryBuilder)(nil) +) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array/boolean.go b/vendor/github.com/apache/arrow/go/v14/arrow/array/boolean.go new file mode 100644 index 000000000..464cef48b --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array/boolean.go @@ -0,0 +1,126 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package array + +import ( + "fmt" + "strconv" + "strings" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/bitutil" + "github.com/apache/arrow/go/v14/arrow/memory" + "github.com/apache/arrow/go/v14/internal/json" +) + +// A type which represents an immutable sequence of boolean values. +type Boolean struct { + array + values []byte +} + +// NewBoolean creates a boolean array from the data memory.Buffer and contains length elements. +// The nullBitmap buffer can be nil of there are no null values. +// If nulls is not known, use UnknownNullCount to calculate the value of NullN at runtime from the nullBitmap buffer. +func NewBoolean(length int, data *memory.Buffer, nullBitmap *memory.Buffer, nulls int) *Boolean { + arrdata := NewData(arrow.FixedWidthTypes.Boolean, length, []*memory.Buffer{nullBitmap, data}, nil, nulls, 0) + defer arrdata.Release() + return NewBooleanData(arrdata) +} + +func NewBooleanData(data arrow.ArrayData) *Boolean { + a := &Boolean{} + a.refCount = 1 + a.setData(data.(*Data)) + return a +} + +func (a *Boolean) Value(i int) bool { + if i < 0 || i >= a.array.data.length { + panic("arrow/array: index out of range") + } + return bitutil.BitIsSet(a.values, a.array.data.offset+i) +} + +func (a *Boolean) ValueStr(i int) string { + if a.IsNull(i) { + return NullValueStr + } else { + return strconv.FormatBool(a.Value(i)) + } +} + +func (a *Boolean) String() string { + o := new(strings.Builder) + o.WriteString("[") + for i := 0; i < a.Len(); i++ { + if i > 0 { + fmt.Fprintf(o, " ") + } + switch { + case a.IsNull(i): + o.WriteString(NullValueStr) + default: + fmt.Fprintf(o, "%v", a.Value(i)) + } + } + o.WriteString("]") + return o.String() +} + +func (a *Boolean) setData(data *Data) { + a.array.setData(data) + vals := data.buffers[1] + if vals != nil { + a.values = vals.Bytes() + } +} + +func (a *Boolean) GetOneForMarshal(i int) interface{} { + if a.IsValid(i) { + return a.Value(i) + } + return nil +} + +func (a *Boolean) MarshalJSON() ([]byte, error) { + vals := make([]interface{}, a.Len()) + for i := 0; i < a.Len(); i++ { + if a.IsValid(i) { + vals[i] = a.Value(i) + } else { + vals[i] = nil + } + } + return json.Marshal(vals) +} + +func arrayEqualBoolean(left, right *Boolean) bool { + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + if left.Value(i) != right.Value(i) { + return false + } + } + return true +} + +var ( + _ arrow.Array = (*Boolean)(nil) +) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array/booleanbuilder.go b/vendor/github.com/apache/arrow/go/v14/arrow/array/booleanbuilder.go new file mode 100644 index 000000000..10b7405aa --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array/booleanbuilder.go @@ -0,0 +1,263 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package array + +import ( + "bytes" + "fmt" + "reflect" + "strconv" + "sync/atomic" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/bitutil" + "github.com/apache/arrow/go/v14/arrow/internal/debug" + "github.com/apache/arrow/go/v14/arrow/memory" + "github.com/apache/arrow/go/v14/internal/json" +) + +type BooleanBuilder struct { + builder + + data *memory.Buffer + rawData []byte +} + +func NewBooleanBuilder(mem memory.Allocator) *BooleanBuilder { + return &BooleanBuilder{builder: builder{refCount: 1, mem: mem}} +} + +func (b *BooleanBuilder) Type() arrow.DataType { return arrow.FixedWidthTypes.Boolean } + +// Release decreases the reference count by 1. +// When the reference count goes to zero, the memory is freed. +// Release may be called simultaneously from multiple goroutines. +func (b *BooleanBuilder) Release() { + debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases") + + if atomic.AddInt64(&b.refCount, -1) == 0 { + if b.nullBitmap != nil { + b.nullBitmap.Release() + b.nullBitmap = nil + } + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + } +} + +func (b *BooleanBuilder) Append(v bool) { + b.Reserve(1) + b.UnsafeAppend(v) +} + +func (b *BooleanBuilder) AppendByte(v byte) { + b.Reserve(1) + b.UnsafeAppend(v != 0) +} + +func (b *BooleanBuilder) AppendNull() { + b.Reserve(1) + b.UnsafeAppendBoolToBitmap(false) +} + +func (b *BooleanBuilder) AppendNulls(n int) { + for i := 0; i < n; i++ { + b.AppendNull() + } +} + +func (b *BooleanBuilder) AppendEmptyValue() { + b.Reserve(1) + b.UnsafeAppend(false) +} + +func (b *BooleanBuilder) AppendEmptyValues(n int) { + for i := 0; i < n; i++ { + b.AppendEmptyValue() + } +} + +func (b *BooleanBuilder) AppendValueFromString(s string) error { + if s == NullValueStr { + b.AppendNull() + return nil + } + val, err := strconv.ParseBool(s) + if err != nil { + return err + } + b.Append(val) + return nil +} + +func (b *BooleanBuilder) UnsafeAppend(v bool) { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + if v { + bitutil.SetBit(b.rawData, b.length) + } else { + bitutil.ClearBit(b.rawData, b.length) + } + b.length++ +} + +func (b *BooleanBuilder) AppendValues(v []bool, valid []bool) { + if len(v) != len(valid) && len(valid) != 0 { + panic("len(v) != len(valid) && len(valid) != 0") + } + + if len(v) == 0 { + return + } + + b.Reserve(len(v)) + for i, vv := range v { + bitutil.SetBitTo(b.rawData, b.length+i, vv) + } + b.builder.unsafeAppendBoolsToBitmap(valid, len(v)) +} + +func (b *BooleanBuilder) init(capacity int) { + b.builder.init(capacity) + + b.data = memory.NewResizableBuffer(b.mem) + bytesN := arrow.BooleanTraits.BytesRequired(capacity) + b.data.Resize(bytesN) + b.rawData = b.data.Bytes() +} + +// Reserve ensures there is enough space for appending n elements +// by checking the capacity and calling Resize if necessary. +func (b *BooleanBuilder) Reserve(n int) { + b.builder.reserve(n, b.Resize) +} + +// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(), +// additional memory will be allocated. If n is smaller, the allocated memory may reduced. +func (b *BooleanBuilder) Resize(n int) { + if n < minBuilderCapacity { + n = minBuilderCapacity + } + + if b.capacity == 0 { + b.init(n) + } else { + b.builder.resize(n, b.init) + b.data.Resize(arrow.BooleanTraits.BytesRequired(n)) + b.rawData = b.data.Bytes() + } +} + +// NewArray creates a Boolean array from the memory buffers used by the builder and resets the BooleanBuilder +// so it can be used to build a new array. +func (b *BooleanBuilder) NewArray() arrow.Array { + return b.NewBooleanArray() +} + +// NewBooleanArray creates a Boolean array from the memory buffers used by the builder and resets the BooleanBuilder +// so it can be used to build a new array. +func (b *BooleanBuilder) NewBooleanArray() (a *Boolean) { + data := b.newData() + a = NewBooleanData(data) + data.Release() + return +} + +func (b *BooleanBuilder) newData() *Data { + bytesRequired := arrow.BooleanTraits.BytesRequired(b.length) + if bytesRequired > 0 && bytesRequired < b.data.Len() { + // trim buffers + b.data.Resize(bytesRequired) + } + res := NewData(arrow.FixedWidthTypes.Boolean, b.length, []*memory.Buffer{b.nullBitmap, b.data}, nil, b.nulls, 0) + b.reset() + + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + + return res +} + +func (b *BooleanBuilder) UnmarshalOne(dec *json.Decoder) error { + t, err := dec.Token() + if err != nil { + return err + } + + switch v := t.(type) { + case bool: + b.Append(v) + case string: + val, err := strconv.ParseBool(v) + if err != nil { + return err + } + b.Append(val) + case json.Number: + val, err := strconv.ParseBool(v.String()) + if err != nil { + return err + } + b.Append(val) + case nil: + b.AppendNull() + default: + return &json.UnmarshalTypeError{ + Value: fmt.Sprint(t), + Type: reflect.TypeOf(true), + Offset: dec.InputOffset(), + } + } + return nil +} + +func (b *BooleanBuilder) Unmarshal(dec *json.Decoder) error { + for dec.More() { + if err := b.UnmarshalOne(dec); err != nil { + return err + } + } + return nil +} + +func (b *BooleanBuilder) UnmarshalJSON(data []byte) error { + dec := json.NewDecoder(bytes.NewReader(data)) + dec.UseNumber() + t, err := dec.Token() + if err != nil { + return err + } + + if delim, ok := t.(json.Delim); !ok || delim != '[' { + return fmt.Errorf("boolean builder must unpack from json array, found %s", delim) + } + + return b.Unmarshal(dec) +} + +func (b *BooleanBuilder) Value(i int) bool { + return bitutil.BitIsSet(b.rawData, i) +} + +var ( + _ Builder = (*BooleanBuilder)(nil) +) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array/bufferbuilder.go b/vendor/github.com/apache/arrow/go/v14/arrow/array/bufferbuilder.go new file mode 100644 index 000000000..e023b0d90 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array/bufferbuilder.go @@ -0,0 +1,153 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package array + +import ( + "sync/atomic" + + "github.com/apache/arrow/go/v14/arrow/bitutil" + "github.com/apache/arrow/go/v14/arrow/internal/debug" + "github.com/apache/arrow/go/v14/arrow/memory" +) + +type bufBuilder interface { + Retain() + Release() + Len() int + Cap() int + Bytes() []byte + resize(int) + Advance(int) + SetLength(int) + Append([]byte) + Reset() + Finish() *memory.Buffer +} + +// A bufferBuilder provides common functionality for populating memory with a sequence of type-specific values. +// Specialized implementations provide type-safe APIs for appending and accessing the memory. +type bufferBuilder struct { + refCount int64 + mem memory.Allocator + buffer *memory.Buffer + length int + capacity int + + bytes []byte +} + +// Retain increases the reference count by 1. +// Retain may be called simultaneously from multiple goroutines. +func (b *bufferBuilder) Retain() { + atomic.AddInt64(&b.refCount, 1) +} + +// Release decreases the reference count by 1. +// When the reference count goes to zero, the memory is freed. +// Release may be called simultaneously from multiple goroutines. +func (b *bufferBuilder) Release() { + debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases") + + if atomic.AddInt64(&b.refCount, -1) == 0 { + if b.buffer != nil { + b.buffer.Release() + b.buffer, b.bytes = nil, nil + } + } +} + +// Len returns the length of the memory buffer in bytes. +func (b *bufferBuilder) Len() int { return b.length } + +// Cap returns the total number of bytes that can be stored without allocating additional memory. +func (b *bufferBuilder) Cap() int { return b.capacity } + +// Bytes returns a slice of length b.Len(). +// The slice is only valid for use until the next buffer modification. That is, until the next call +// to Advance, Reset, Finish or any Append function. The slice aliases the buffer content at least until the next +// buffer modification. +func (b *bufferBuilder) Bytes() []byte { return b.bytes[:b.length] } + +func (b *bufferBuilder) resize(elements int) { + if b.buffer == nil { + b.buffer = memory.NewResizableBuffer(b.mem) + } + + b.buffer.ResizeNoShrink(elements) + oldCapacity := b.capacity + b.capacity = b.buffer.Cap() + b.bytes = b.buffer.Buf() + + if b.capacity > oldCapacity { + memory.Set(b.bytes[oldCapacity:], 0) + } +} + +func (b *bufferBuilder) SetLength(length int) { + if length > b.length { + b.Advance(length) + return + } + + b.length = length +} + +// Advance increases the buffer by length and initializes the skipped bytes to zero. +func (b *bufferBuilder) Advance(length int) { + if b.capacity < b.length+length { + newCapacity := bitutil.NextPowerOf2(b.length + length) + b.resize(newCapacity) + } + b.length += length +} + +// Append appends the contents of v to the buffer, resizing it if necessary. +func (b *bufferBuilder) Append(v []byte) { + if b.capacity < b.length+len(v) { + newCapacity := bitutil.NextPowerOf2(b.length + len(v)) + b.resize(newCapacity) + } + b.unsafeAppend(v) +} + +// Reset returns the buffer to an empty state. Reset releases the memory and sets the length and capacity to zero. +func (b *bufferBuilder) Reset() { + if b.buffer != nil { + b.buffer.Release() + } + b.buffer, b.bytes = nil, nil + b.capacity, b.length = 0, 0 +} + +// Finish TODO(sgc) +func (b *bufferBuilder) Finish() (buffer *memory.Buffer) { + if b.length > 0 { + b.buffer.ResizeNoShrink(b.length) + } + buffer = b.buffer + b.buffer = nil + b.Reset() + if buffer == nil { + buffer = memory.NewBufferBytes(nil) + } + return +} + +func (b *bufferBuilder) unsafeAppend(data []byte) { + copy(b.bytes[b.length:], data) + b.length += len(data) +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array/bufferbuilder_byte.go b/vendor/github.com/apache/arrow/go/v14/arrow/array/bufferbuilder_byte.go new file mode 100644 index 000000000..00a0d1c21 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array/bufferbuilder_byte.go @@ -0,0 +1,30 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package array + +import "github.com/apache/arrow/go/v14/arrow/memory" + +type byteBufferBuilder struct { + bufferBuilder +} + +func newByteBufferBuilder(mem memory.Allocator) *byteBufferBuilder { + return &byteBufferBuilder{bufferBuilder: bufferBuilder{refCount: 1, mem: mem}} +} + +func (b *byteBufferBuilder) Values() []byte { return b.Bytes() } +func (b *byteBufferBuilder) Value(i int) byte { return b.bytes[i] } diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array/bufferbuilder_numeric.gen.go b/vendor/github.com/apache/arrow/go/v14/arrow/array/bufferbuilder_numeric.gen.go new file mode 100644 index 000000000..879bc9f57 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array/bufferbuilder_numeric.gen.go @@ -0,0 +1,124 @@ +// Code generated by array/bufferbuilder_numeric.gen.go.tmpl. DO NOT EDIT. + +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package array + +import ( + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/bitutil" + "github.com/apache/arrow/go/v14/arrow/memory" +) + +type int64BufferBuilder struct { + bufferBuilder +} + +func newInt64BufferBuilder(mem memory.Allocator) *int64BufferBuilder { + return &int64BufferBuilder{bufferBuilder: bufferBuilder{refCount: 1, mem: mem}} +} + +// AppendValues appends the contents of v to the buffer, growing the buffer as needed. +func (b *int64BufferBuilder) AppendValues(v []int64) { b.Append(arrow.Int64Traits.CastToBytes(v)) } + +// Values returns a slice of length b.Len(). +// The slice is only valid for use until the next buffer modification. That is, until the next call +// to Advance, Reset, Finish or any Append function. The slice aliases the buffer content at least until the next +// buffer modification. +func (b *int64BufferBuilder) Values() []int64 { return arrow.Int64Traits.CastFromBytes(b.Bytes()) } + +// Value returns the int64 element at the index i. Value will panic if i is negative or ≥ Len. +func (b *int64BufferBuilder) Value(i int) int64 { return b.Values()[i] } + +// Len returns the number of int64 elements in the buffer. +func (b *int64BufferBuilder) Len() int { return b.length / arrow.Int64SizeBytes } + +// AppendValue appends v to the buffer, growing the buffer as needed. +func (b *int64BufferBuilder) AppendValue(v int64) { + if b.capacity < b.length+arrow.Int64SizeBytes { + newCapacity := bitutil.NextPowerOf2(b.length + arrow.Int64SizeBytes) + b.resize(newCapacity) + } + arrow.Int64Traits.PutValue(b.bytes[b.length:], v) + b.length += arrow.Int64SizeBytes +} + +type int32BufferBuilder struct { + bufferBuilder +} + +func newInt32BufferBuilder(mem memory.Allocator) *int32BufferBuilder { + return &int32BufferBuilder{bufferBuilder: bufferBuilder{refCount: 1, mem: mem}} +} + +// AppendValues appends the contents of v to the buffer, growing the buffer as needed. +func (b *int32BufferBuilder) AppendValues(v []int32) { b.Append(arrow.Int32Traits.CastToBytes(v)) } + +// Values returns a slice of length b.Len(). +// The slice is only valid for use until the next buffer modification. That is, until the next call +// to Advance, Reset, Finish or any Append function. The slice aliases the buffer content at least until the next +// buffer modification. +func (b *int32BufferBuilder) Values() []int32 { return arrow.Int32Traits.CastFromBytes(b.Bytes()) } + +// Value returns the int32 element at the index i. Value will panic if i is negative or ≥ Len. +func (b *int32BufferBuilder) Value(i int) int32 { return b.Values()[i] } + +// Len returns the number of int32 elements in the buffer. +func (b *int32BufferBuilder) Len() int { return b.length / arrow.Int32SizeBytes } + +// AppendValue appends v to the buffer, growing the buffer as needed. +func (b *int32BufferBuilder) AppendValue(v int32) { + if b.capacity < b.length+arrow.Int32SizeBytes { + newCapacity := bitutil.NextPowerOf2(b.length + arrow.Int32SizeBytes) + b.resize(newCapacity) + } + arrow.Int32Traits.PutValue(b.bytes[b.length:], v) + b.length += arrow.Int32SizeBytes +} + +type int8BufferBuilder struct { + bufferBuilder +} + +func newInt8BufferBuilder(mem memory.Allocator) *int8BufferBuilder { + return &int8BufferBuilder{bufferBuilder: bufferBuilder{refCount: 1, mem: mem}} +} + +// AppendValues appends the contents of v to the buffer, growing the buffer as needed. +func (b *int8BufferBuilder) AppendValues(v []int8) { b.Append(arrow.Int8Traits.CastToBytes(v)) } + +// Values returns a slice of length b.Len(). +// The slice is only valid for use until the next buffer modification. That is, until the next call +// to Advance, Reset, Finish or any Append function. The slice aliases the buffer content at least until the next +// buffer modification. +func (b *int8BufferBuilder) Values() []int8 { return arrow.Int8Traits.CastFromBytes(b.Bytes()) } + +// Value returns the int8 element at the index i. Value will panic if i is negative or ≥ Len. +func (b *int8BufferBuilder) Value(i int) int8 { return b.Values()[i] } + +// Len returns the number of int8 elements in the buffer. +func (b *int8BufferBuilder) Len() int { return b.length / arrow.Int8SizeBytes } + +// AppendValue appends v to the buffer, growing the buffer as needed. +func (b *int8BufferBuilder) AppendValue(v int8) { + if b.capacity < b.length+arrow.Int8SizeBytes { + newCapacity := bitutil.NextPowerOf2(b.length + arrow.Int8SizeBytes) + b.resize(newCapacity) + } + arrow.Int8Traits.PutValue(b.bytes[b.length:], v) + b.length += arrow.Int8SizeBytes +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array/bufferbuilder_numeric.gen.go.tmpl b/vendor/github.com/apache/arrow/go/v14/arrow/array/bufferbuilder_numeric.gen.go.tmpl new file mode 100644 index 000000000..e859b5bff --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array/bufferbuilder_numeric.gen.go.tmpl @@ -0,0 +1,61 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package array + +import ( + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/bitutil" + "github.com/apache/arrow/go/v14/arrow/memory" +) + +{{range .In}} +{{$TypeNamePrefix := .name}} +{{if .Opt.BufferBuilder}} +type {{$TypeNamePrefix}}BufferBuilder struct { + bufferBuilder +} + +func new{{.Name}}BufferBuilder(mem memory.Allocator) *{{$TypeNamePrefix}}BufferBuilder { + return &{{$TypeNamePrefix}}BufferBuilder{bufferBuilder:bufferBuilder{refCount: 1, mem:mem}} +} + +// AppendValues appends the contents of v to the buffer, growing the buffer as needed. +func (b *{{$TypeNamePrefix}}BufferBuilder) AppendValues(v []{{.Type}}) { b.Append(arrow.{{.Name}}Traits.CastToBytes(v)) } + +// Values returns a slice of length b.Len(). +// The slice is only valid for use until the next buffer modification. That is, until the next call +// to Advance, Reset, Finish or any Append function. The slice aliases the buffer content at least until the next +// buffer modification. +func (b *{{$TypeNamePrefix}}BufferBuilder) Values() []{{.Type}} { return arrow.{{.Name}}Traits.CastFromBytes(b.Bytes()) } + +// Value returns the {{.Type}} element at the index i. Value will panic if i is negative or ≥ Len. +func (b *{{$TypeNamePrefix}}BufferBuilder) Value(i int) {{.Type}} { return b.Values()[i] } + +// Len returns the number of {{.Type}} elements in the buffer. +func (b *{{$TypeNamePrefix}}BufferBuilder) Len() int { return b.length/arrow.{{.Name}}SizeBytes } + +// AppendValue appends v to the buffer, growing the buffer as needed. +func (b *{{$TypeNamePrefix}}BufferBuilder) AppendValue(v {{.Type}}) { + if b.capacity < b.length+arrow.{{.Name}}SizeBytes { + newCapacity := bitutil.NextPowerOf2(b.length + arrow.{{.Name}}SizeBytes) + b.resize(newCapacity) + } + arrow.{{.Name}}Traits.PutValue(b.bytes[b.length:], v) + b.length+=arrow.{{.Name}}SizeBytes +} +{{end}} +{{end}} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array/builder.go b/vendor/github.com/apache/arrow/go/v14/arrow/array/builder.go new file mode 100644 index 000000000..2f15ac965 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array/builder.go @@ -0,0 +1,369 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package array + +import ( + "fmt" + "sync/atomic" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/bitutil" + "github.com/apache/arrow/go/v14/arrow/memory" + "github.com/apache/arrow/go/v14/internal/json" +) + +const ( + minBuilderCapacity = 1 << 5 +) + +// Builder provides an interface to build arrow arrays. +type Builder interface { + // you can unmarshal a json array to add the values to a builder + json.Unmarshaler + + // Type returns the datatype that this is building + Type() arrow.DataType + + // Retain increases the reference count by 1. + // Retain may be called simultaneously from multiple goroutines. + Retain() + + // Release decreases the reference count by 1. + Release() + + // Len returns the number of elements in the array builder. + Len() int + + // Cap returns the total number of elements that can be stored + // without allocating additional memory. + Cap() int + + // NullN returns the number of null values in the array builder. + NullN() int + + // AppendNull adds a new null value to the array being built. + AppendNull() + + // AppendNulls adds new n null values to the array being built. + AppendNulls(n int) + + // AppendEmptyValue adds a new zero value of the appropriate type + AppendEmptyValue() + + // AppendEmptyValues adds new n zero values of the appropriate type + AppendEmptyValues(n int) + + // AppendValueFromString adds a new value from a string. Inverse of array.ValueStr(i int) string + AppendValueFromString(string) error + + // Reserve ensures there is enough space for appending n elements + // by checking the capacity and calling Resize if necessary. + Reserve(n int) + + // Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(), + // additional memory will be allocated. If n is smaller, the allocated memory may reduced. + Resize(n int) + + // NewArray creates a new array from the memory buffers used + // by the builder and resets the Builder so it can be used to build + // a new array. + NewArray() arrow.Array + + // IsNull returns if a previously appended value at a given index is null or not. + IsNull(i int) bool + + // SetNull sets the value at index i to null. + SetNull(i int) + + UnsafeAppendBoolToBitmap(bool) + + init(capacity int) + resize(newBits int, init func(int)) + + UnmarshalOne(*json.Decoder) error + Unmarshal(*json.Decoder) error + + newData() *Data +} + +// builder provides common functionality for managing the validity bitmap (nulls) when building arrays. +type builder struct { + refCount int64 + mem memory.Allocator + nullBitmap *memory.Buffer + nulls int + length int + capacity int +} + +// Retain increases the reference count by 1. +// Retain may be called simultaneously from multiple goroutines. +func (b *builder) Retain() { + atomic.AddInt64(&b.refCount, 1) +} + +// Len returns the number of elements in the array builder. +func (b *builder) Len() int { return b.length } + +// Cap returns the total number of elements that can be stored without allocating additional memory. +func (b *builder) Cap() int { return b.capacity } + +// NullN returns the number of null values in the array builder. +func (b *builder) NullN() int { return b.nulls } + +func (b *builder) IsNull(i int) bool { + return b.nullBitmap.Len() != 0 && bitutil.BitIsNotSet(b.nullBitmap.Bytes(), i) +} + +func (b *builder) SetNull(i int) { + if i < 0 || i >= b.length { + panic("arrow/array: index out of range") + } + bitutil.ClearBit(b.nullBitmap.Bytes(), i) +} + +func (b *builder) init(capacity int) { + toAlloc := bitutil.CeilByte(capacity) / 8 + b.nullBitmap = memory.NewResizableBuffer(b.mem) + b.nullBitmap.Resize(toAlloc) + b.capacity = capacity + memory.Set(b.nullBitmap.Buf(), 0) +} + +func (b *builder) reset() { + if b.nullBitmap != nil { + b.nullBitmap.Release() + b.nullBitmap = nil + } + + b.nulls = 0 + b.length = 0 + b.capacity = 0 +} + +func (b *builder) resize(newBits int, init func(int)) { + if b.nullBitmap == nil { + init(newBits) + return + } + + newBytesN := bitutil.CeilByte(newBits) / 8 + oldBytesN := b.nullBitmap.Len() + b.nullBitmap.Resize(newBytesN) + b.capacity = newBits + if oldBytesN < newBytesN { + // TODO(sgc): necessary? + memory.Set(b.nullBitmap.Buf()[oldBytesN:], 0) + } + if newBits < b.length { + b.length = newBits + b.nulls = newBits - bitutil.CountSetBits(b.nullBitmap.Buf(), 0, newBits) + } +} + +func (b *builder) reserve(elements int, resize func(int)) { + if b.nullBitmap == nil { + b.nullBitmap = memory.NewResizableBuffer(b.mem) + } + if b.length+elements > b.capacity { + newCap := bitutil.NextPowerOf2(b.length + elements) + resize(newCap) + } +} + +// unsafeAppendBoolsToBitmap appends the contents of valid to the validity bitmap. +// As an optimization, if the valid slice is empty, the next length bits will be set to valid (not null). +func (b *builder) unsafeAppendBoolsToBitmap(valid []bool, length int) { + if len(valid) == 0 { + b.unsafeSetValid(length) + return + } + + byteOffset := b.length / 8 + bitOffset := byte(b.length % 8) + nullBitmap := b.nullBitmap.Bytes() + bitSet := nullBitmap[byteOffset] + + for _, v := range valid { + if bitOffset == 8 { + bitOffset = 0 + nullBitmap[byteOffset] = bitSet + byteOffset++ + bitSet = nullBitmap[byteOffset] + } + + if v { + bitSet |= bitutil.BitMask[bitOffset] + } else { + bitSet &= bitutil.FlippedBitMask[bitOffset] + b.nulls++ + } + bitOffset++ + } + + if bitOffset != 0 { + nullBitmap[byteOffset] = bitSet + } + b.length += len(valid) +} + +// unsafeSetValid sets the next length bits to valid in the validity bitmap. +func (b *builder) unsafeSetValid(length int) { + padToByte := min(8-(b.length%8), length) + if padToByte == 8 { + padToByte = 0 + } + bits := b.nullBitmap.Bytes() + for i := b.length; i < b.length+padToByte; i++ { + bitutil.SetBit(bits, i) + } + + start := (b.length + padToByte) / 8 + fastLength := (length - padToByte) / 8 + memory.Set(bits[start:start+fastLength], 0xff) + + newLength := b.length + length + // trailing bytes + for i := b.length + padToByte + (fastLength * 8); i < newLength; i++ { + bitutil.SetBit(bits, i) + } + + b.length = newLength +} + +func (b *builder) UnsafeAppendBoolToBitmap(isValid bool) { + if isValid { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + } else { + b.nulls++ + } + b.length++ +} + +func NewBuilder(mem memory.Allocator, dtype arrow.DataType) Builder { + // FIXME(sbinet): use a type switch on dtype instead? + switch dtype.ID() { + case arrow.NULL: + return NewNullBuilder(mem) + case arrow.BOOL: + return NewBooleanBuilder(mem) + case arrow.UINT8: + return NewUint8Builder(mem) + case arrow.INT8: + return NewInt8Builder(mem) + case arrow.UINT16: + return NewUint16Builder(mem) + case arrow.INT16: + return NewInt16Builder(mem) + case arrow.UINT32: + return NewUint32Builder(mem) + case arrow.INT32: + return NewInt32Builder(mem) + case arrow.UINT64: + return NewUint64Builder(mem) + case arrow.INT64: + return NewInt64Builder(mem) + case arrow.FLOAT16: + return NewFloat16Builder(mem) + case arrow.FLOAT32: + return NewFloat32Builder(mem) + case arrow.FLOAT64: + return NewFloat64Builder(mem) + case arrow.STRING: + return NewStringBuilder(mem) + case arrow.LARGE_STRING: + return NewLargeStringBuilder(mem) + case arrow.BINARY: + return NewBinaryBuilder(mem, arrow.BinaryTypes.Binary) + case arrow.LARGE_BINARY: + return NewBinaryBuilder(mem, arrow.BinaryTypes.LargeBinary) + case arrow.FIXED_SIZE_BINARY: + typ := dtype.(*arrow.FixedSizeBinaryType) + return NewFixedSizeBinaryBuilder(mem, typ) + case arrow.DATE32: + return NewDate32Builder(mem) + case arrow.DATE64: + return NewDate64Builder(mem) + case arrow.TIMESTAMP: + typ := dtype.(*arrow.TimestampType) + return NewTimestampBuilder(mem, typ) + case arrow.TIME32: + typ := dtype.(*arrow.Time32Type) + return NewTime32Builder(mem, typ) + case arrow.TIME64: + typ := dtype.(*arrow.Time64Type) + return NewTime64Builder(mem, typ) + case arrow.INTERVAL_MONTHS: + return NewMonthIntervalBuilder(mem) + case arrow.INTERVAL_DAY_TIME: + return NewDayTimeIntervalBuilder(mem) + case arrow.INTERVAL_MONTH_DAY_NANO: + return NewMonthDayNanoIntervalBuilder(mem) + case arrow.DECIMAL128: + if typ, ok := dtype.(*arrow.Decimal128Type); ok { + return NewDecimal128Builder(mem, typ) + } + case arrow.DECIMAL256: + if typ, ok := dtype.(*arrow.Decimal256Type); ok { + return NewDecimal256Builder(mem, typ) + } + case arrow.LIST: + typ := dtype.(*arrow.ListType) + return NewListBuilderWithField(mem, typ.ElemField()) + case arrow.STRUCT: + typ := dtype.(*arrow.StructType) + return NewStructBuilder(mem, typ) + case arrow.SPARSE_UNION: + typ := dtype.(*arrow.SparseUnionType) + return NewSparseUnionBuilder(mem, typ) + case arrow.DENSE_UNION: + typ := dtype.(*arrow.DenseUnionType) + return NewDenseUnionBuilder(mem, typ) + case arrow.DICTIONARY: + typ := dtype.(*arrow.DictionaryType) + return NewDictionaryBuilder(mem, typ) + case arrow.LARGE_LIST: + typ := dtype.(*arrow.LargeListType) + return NewLargeListBuilderWithField(mem, typ.ElemField()) + case arrow.MAP: + typ := dtype.(*arrow.MapType) + return NewMapBuilderWithType(mem, typ) + case arrow.LIST_VIEW: + typ := dtype.(*arrow.ListViewType) + return NewListViewBuilderWithField(mem, typ.ElemField()) + case arrow.LARGE_LIST_VIEW: + typ := dtype.(*arrow.LargeListViewType) + return NewLargeListViewBuilderWithField(mem, typ.ElemField()) + case arrow.EXTENSION: + typ := dtype.(arrow.ExtensionType) + bldr := NewExtensionBuilder(mem, typ) + if custom, ok := typ.(ExtensionBuilderWrapper); ok { + return custom.NewBuilder(bldr) + } + return bldr + case arrow.FIXED_SIZE_LIST: + typ := dtype.(*arrow.FixedSizeListType) + return NewFixedSizeListBuilder(mem, typ.Len(), typ.Elem()) + case arrow.DURATION: + typ := dtype.(*arrow.DurationType) + return NewDurationBuilder(mem, typ) + case arrow.RUN_END_ENCODED: + typ := dtype.(*arrow.RunEndEncodedType) + return NewRunEndEncodedBuilder(mem, typ.RunEnds(), typ.Encoded()) + } + panic(fmt.Errorf("arrow/array: unsupported builder for %T", dtype)) +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array/compare.go b/vendor/github.com/apache/arrow/go/v14/arrow/array/compare.go new file mode 100644 index 000000000..e70716bee --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array/compare.go @@ -0,0 +1,842 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package array + +import ( + "fmt" + "math" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/float16" + "github.com/apache/arrow/go/v14/internal/bitutils" +) + +// RecordEqual reports whether the two provided records are equal. +func RecordEqual(left, right arrow.Record) bool { + switch { + case left.NumCols() != right.NumCols(): + return false + case left.NumRows() != right.NumRows(): + return false + } + + for i := range left.Columns() { + lc := left.Column(i) + rc := right.Column(i) + if !Equal(lc, rc) { + return false + } + } + return true +} + +// RecordApproxEqual reports whether the two provided records are approximately equal. +// For non-floating point columns, it is equivalent to RecordEqual. +func RecordApproxEqual(left, right arrow.Record, opts ...EqualOption) bool { + switch { + case left.NumCols() != right.NumCols(): + return false + case left.NumRows() != right.NumRows(): + return false + } + + opt := newEqualOption(opts...) + + for i := range left.Columns() { + lc := left.Column(i) + rc := right.Column(i) + if !arrayApproxEqual(lc, rc, opt) { + return false + } + } + return true +} + +// helper function to evaluate a function on two chunked object having possibly different +// chunk layouts. the function passed in will be called for each corresponding slice of the +// two chunked arrays and if the function returns false it will end the loop early. +func chunkedBinaryApply(left, right *arrow.Chunked, fn func(left arrow.Array, lbeg, lend int64, right arrow.Array, rbeg, rend int64) bool) { + var ( + pos int64 + length int64 = int64(left.Len()) + leftIdx, rightIdx int + leftPos, rightPos int64 + ) + + for pos < length { + var cleft, cright arrow.Array + for { + cleft, cright = left.Chunk(leftIdx), right.Chunk(rightIdx) + if leftPos == int64(cleft.Len()) { + leftPos = 0 + leftIdx++ + continue + } + if rightPos == int64(cright.Len()) { + rightPos = 0 + rightIdx++ + continue + } + break + } + + sz := int64(min(cleft.Len()-int(leftPos), cright.Len()-int(rightPos))) + pos += sz + if !fn(cleft, leftPos, leftPos+sz, cright, rightPos, rightPos+sz) { + return + } + + leftPos += sz + rightPos += sz + } +} + +// ChunkedEqual reports whether two chunked arrays are equal regardless of their chunkings +func ChunkedEqual(left, right *arrow.Chunked) bool { + switch { + case left == right: + return true + case left.Len() != right.Len(): + return false + case left.NullN() != right.NullN(): + return false + case !arrow.TypeEqual(left.DataType(), right.DataType()): + return false + } + + var isequal bool = true + chunkedBinaryApply(left, right, func(left arrow.Array, lbeg, lend int64, right arrow.Array, rbeg, rend int64) bool { + isequal = SliceEqual(left, lbeg, lend, right, rbeg, rend) + return isequal + }) + + return isequal +} + +// ChunkedApproxEqual reports whether two chunked arrays are approximately equal regardless of their chunkings +// for non-floating point arrays, this is equivalent to ChunkedEqual +func ChunkedApproxEqual(left, right *arrow.Chunked, opts ...EqualOption) bool { + switch { + case left == right: + return true + case left.Len() != right.Len(): + return false + case left.NullN() != right.NullN(): + return false + case !arrow.TypeEqual(left.DataType(), right.DataType()): + return false + } + + var isequal bool + chunkedBinaryApply(left, right, func(left arrow.Array, lbeg, lend int64, right arrow.Array, rbeg, rend int64) bool { + isequal = SliceApproxEqual(left, lbeg, lend, right, rbeg, rend, opts...) + return isequal + }) + + return isequal +} + +// TableEqual returns if the two tables have the same data in the same schema +func TableEqual(left, right arrow.Table) bool { + switch { + case left.NumCols() != right.NumCols(): + return false + case left.NumRows() != right.NumRows(): + return false + } + + for i := 0; int64(i) < left.NumCols(); i++ { + lc := left.Column(i) + rc := right.Column(i) + if !lc.Field().Equal(rc.Field()) { + return false + } + + if !ChunkedEqual(lc.Data(), rc.Data()) { + return false + } + } + return true +} + +// TableEqual returns if the two tables have the approximately equal data in the same schema +func TableApproxEqual(left, right arrow.Table, opts ...EqualOption) bool { + switch { + case left.NumCols() != right.NumCols(): + return false + case left.NumRows() != right.NumRows(): + return false + } + + for i := 0; int64(i) < left.NumCols(); i++ { + lc := left.Column(i) + rc := right.Column(i) + if !lc.Field().Equal(rc.Field()) { + return false + } + + if !ChunkedApproxEqual(lc.Data(), rc.Data(), opts...) { + return false + } + } + return true +} + +// Equal reports whether the two provided arrays are equal. +func Equal(left, right arrow.Array) bool { + switch { + case !baseArrayEqual(left, right): + return false + case left.Len() == 0: + return true + case left.NullN() == left.Len(): + return true + } + + // at this point, we know both arrays have same type, same length, same number of nulls + // and nulls at the same place. + // compare the values. + + switch l := left.(type) { + case *Null: + return true + case *Boolean: + r := right.(*Boolean) + return arrayEqualBoolean(l, r) + case *FixedSizeBinary: + r := right.(*FixedSizeBinary) + return arrayEqualFixedSizeBinary(l, r) + case *Binary: + r := right.(*Binary) + return arrayEqualBinary(l, r) + case *String: + r := right.(*String) + return arrayEqualString(l, r) + case *LargeBinary: + r := right.(*LargeBinary) + return arrayEqualLargeBinary(l, r) + case *LargeString: + r := right.(*LargeString) + return arrayEqualLargeString(l, r) + case *Int8: + r := right.(*Int8) + return arrayEqualInt8(l, r) + case *Int16: + r := right.(*Int16) + return arrayEqualInt16(l, r) + case *Int32: + r := right.(*Int32) + return arrayEqualInt32(l, r) + case *Int64: + r := right.(*Int64) + return arrayEqualInt64(l, r) + case *Uint8: + r := right.(*Uint8) + return arrayEqualUint8(l, r) + case *Uint16: + r := right.(*Uint16) + return arrayEqualUint16(l, r) + case *Uint32: + r := right.(*Uint32) + return arrayEqualUint32(l, r) + case *Uint64: + r := right.(*Uint64) + return arrayEqualUint64(l, r) + case *Float16: + r := right.(*Float16) + return arrayEqualFloat16(l, r) + case *Float32: + r := right.(*Float32) + return arrayEqualFloat32(l, r) + case *Float64: + r := right.(*Float64) + return arrayEqualFloat64(l, r) + case *Decimal128: + r := right.(*Decimal128) + return arrayEqualDecimal128(l, r) + case *Decimal256: + r := right.(*Decimal256) + return arrayEqualDecimal256(l, r) + case *Date32: + r := right.(*Date32) + return arrayEqualDate32(l, r) + case *Date64: + r := right.(*Date64) + return arrayEqualDate64(l, r) + case *Time32: + r := right.(*Time32) + return arrayEqualTime32(l, r) + case *Time64: + r := right.(*Time64) + return arrayEqualTime64(l, r) + case *Timestamp: + r := right.(*Timestamp) + return arrayEqualTimestamp(l, r) + case *List: + r := right.(*List) + return arrayEqualList(l, r) + case *LargeList: + r := right.(*LargeList) + return arrayEqualLargeList(l, r) + case *ListView: + r := right.(*ListView) + return arrayEqualListView(l, r) + case *LargeListView: + r := right.(*LargeListView) + return arrayEqualLargeListView(l, r) + case *FixedSizeList: + r := right.(*FixedSizeList) + return arrayEqualFixedSizeList(l, r) + case *Struct: + r := right.(*Struct) + return arrayEqualStruct(l, r) + case *MonthInterval: + r := right.(*MonthInterval) + return arrayEqualMonthInterval(l, r) + case *DayTimeInterval: + r := right.(*DayTimeInterval) + return arrayEqualDayTimeInterval(l, r) + case *MonthDayNanoInterval: + r := right.(*MonthDayNanoInterval) + return arrayEqualMonthDayNanoInterval(l, r) + case *Duration: + r := right.(*Duration) + return arrayEqualDuration(l, r) + case *Map: + r := right.(*Map) + return arrayEqualMap(l, r) + case ExtensionArray: + r := right.(ExtensionArray) + return arrayEqualExtension(l, r) + case *Dictionary: + r := right.(*Dictionary) + return arrayEqualDict(l, r) + case *SparseUnion: + r := right.(*SparseUnion) + return arraySparseUnionEqual(l, r) + case *DenseUnion: + r := right.(*DenseUnion) + return arrayDenseUnionEqual(l, r) + case *RunEndEncoded: + r := right.(*RunEndEncoded) + return arrayRunEndEncodedEqual(l, r) + default: + panic(fmt.Errorf("arrow/array: unknown array type %T", l)) + } +} + +// SliceEqual reports whether slices left[lbeg:lend] and right[rbeg:rend] are equal. +func SliceEqual(left arrow.Array, lbeg, lend int64, right arrow.Array, rbeg, rend int64) bool { + l := NewSlice(left, lbeg, lend) + defer l.Release() + r := NewSlice(right, rbeg, rend) + defer r.Release() + + return Equal(l, r) +} + +// SliceApproxEqual reports whether slices left[lbeg:lend] and right[rbeg:rend] are approximately equal. +func SliceApproxEqual(left arrow.Array, lbeg, lend int64, right arrow.Array, rbeg, rend int64, opts ...EqualOption) bool { + opt := newEqualOption(opts...) + return sliceApproxEqual(left, lbeg, lend, right, rbeg, rend, opt) +} + +func sliceApproxEqual(left arrow.Array, lbeg, lend int64, right arrow.Array, rbeg, rend int64, opt equalOption) bool { + l := NewSlice(left, lbeg, lend) + defer l.Release() + r := NewSlice(right, rbeg, rend) + defer r.Release() + + return arrayApproxEqual(l, r, opt) +} + +const defaultAbsoluteTolerance = 1e-5 + +type equalOption struct { + atol float64 // absolute tolerance + nansEq bool // whether NaNs are considered equal. + unorderedMapKeys bool // whether maps are allowed to have different entries order +} + +func (eq equalOption) f16(f1, f2 float16.Num) bool { + v1 := float64(f1.Float32()) + v2 := float64(f2.Float32()) + switch { + case eq.nansEq: + return math.Abs(v1-v2) <= eq.atol || (math.IsNaN(v1) && math.IsNaN(v2)) + default: + return math.Abs(v1-v2) <= eq.atol + } +} + +func (eq equalOption) f32(f1, f2 float32) bool { + v1 := float64(f1) + v2 := float64(f2) + switch { + case eq.nansEq: + return v1 == v2 || math.Abs(v1-v2) <= eq.atol || (math.IsNaN(v1) && math.IsNaN(v2)) + default: + return v1 == v2 || math.Abs(v1-v2) <= eq.atol + } +} + +func (eq equalOption) f64(v1, v2 float64) bool { + switch { + case eq.nansEq: + return v1 == v2 || math.Abs(v1-v2) <= eq.atol || (math.IsNaN(v1) && math.IsNaN(v2)) + default: + return v1 == v2 || math.Abs(v1-v2) <= eq.atol + } +} + +func newEqualOption(opts ...EqualOption) equalOption { + eq := equalOption{ + atol: defaultAbsoluteTolerance, + nansEq: false, + } + for _, opt := range opts { + opt(&eq) + } + + return eq +} + +// EqualOption is a functional option type used to configure how Records and Arrays are compared. +type EqualOption func(*equalOption) + +// WithNaNsEqual configures the comparison functions so that NaNs are considered equal. +func WithNaNsEqual(v bool) EqualOption { + return func(o *equalOption) { + o.nansEq = v + } +} + +// WithAbsTolerance configures the comparison functions so that 2 floating point values +// v1 and v2 are considered equal if |v1-v2| <= atol. +func WithAbsTolerance(atol float64) EqualOption { + return func(o *equalOption) { + o.atol = atol + } +} + +// WithUnorderedMapKeys configures the comparison functions so that Map with different entries order are considered equal. +func WithUnorderedMapKeys(v bool) EqualOption { + return func(o *equalOption) { + o.unorderedMapKeys = v + } +} + +// ApproxEqual reports whether the two provided arrays are approximately equal. +// For non-floating point arrays, it is equivalent to Equal. +func ApproxEqual(left, right arrow.Array, opts ...EqualOption) bool { + opt := newEqualOption(opts...) + return arrayApproxEqual(left, right, opt) +} + +func arrayApproxEqual(left, right arrow.Array, opt equalOption) bool { + switch { + case !baseArrayEqual(left, right): + return false + case left.Len() == 0: + return true + case left.NullN() == left.Len(): + return true + } + + // at this point, we know both arrays have same type, same length, same number of nulls + // and nulls at the same place. + // compare the values. + + switch l := left.(type) { + case *Null: + return true + case *Boolean: + r := right.(*Boolean) + return arrayEqualBoolean(l, r) + case *FixedSizeBinary: + r := right.(*FixedSizeBinary) + return arrayEqualFixedSizeBinary(l, r) + case *Binary: + r := right.(*Binary) + return arrayEqualBinary(l, r) + case *String: + r := right.(*String) + return arrayEqualString(l, r) + case *LargeBinary: + r := right.(*LargeBinary) + return arrayEqualLargeBinary(l, r) + case *LargeString: + r := right.(*LargeString) + return arrayEqualLargeString(l, r) + case *Int8: + r := right.(*Int8) + return arrayEqualInt8(l, r) + case *Int16: + r := right.(*Int16) + return arrayEqualInt16(l, r) + case *Int32: + r := right.(*Int32) + return arrayEqualInt32(l, r) + case *Int64: + r := right.(*Int64) + return arrayEqualInt64(l, r) + case *Uint8: + r := right.(*Uint8) + return arrayEqualUint8(l, r) + case *Uint16: + r := right.(*Uint16) + return arrayEqualUint16(l, r) + case *Uint32: + r := right.(*Uint32) + return arrayEqualUint32(l, r) + case *Uint64: + r := right.(*Uint64) + return arrayEqualUint64(l, r) + case *Float16: + r := right.(*Float16) + return arrayApproxEqualFloat16(l, r, opt) + case *Float32: + r := right.(*Float32) + return arrayApproxEqualFloat32(l, r, opt) + case *Float64: + r := right.(*Float64) + return arrayApproxEqualFloat64(l, r, opt) + case *Decimal128: + r := right.(*Decimal128) + return arrayEqualDecimal128(l, r) + case *Decimal256: + r := right.(*Decimal256) + return arrayEqualDecimal256(l, r) + case *Date32: + r := right.(*Date32) + return arrayEqualDate32(l, r) + case *Date64: + r := right.(*Date64) + return arrayEqualDate64(l, r) + case *Time32: + r := right.(*Time32) + return arrayEqualTime32(l, r) + case *Time64: + r := right.(*Time64) + return arrayEqualTime64(l, r) + case *Timestamp: + r := right.(*Timestamp) + return arrayEqualTimestamp(l, r) + case *List: + r := right.(*List) + return arrayApproxEqualList(l, r, opt) + case *LargeList: + r := right.(*LargeList) + return arrayApproxEqualLargeList(l, r, opt) + case *ListView: + r := right.(*ListView) + return arrayApproxEqualListView(l, r, opt) + case *LargeListView: + r := right.(*LargeListView) + return arrayApproxEqualLargeListView(l, r, opt) + case *FixedSizeList: + r := right.(*FixedSizeList) + return arrayApproxEqualFixedSizeList(l, r, opt) + case *Struct: + r := right.(*Struct) + return arrayApproxEqualStruct(l, r, opt) + case *MonthInterval: + r := right.(*MonthInterval) + return arrayEqualMonthInterval(l, r) + case *DayTimeInterval: + r := right.(*DayTimeInterval) + return arrayEqualDayTimeInterval(l, r) + case *MonthDayNanoInterval: + r := right.(*MonthDayNanoInterval) + return arrayEqualMonthDayNanoInterval(l, r) + case *Duration: + r := right.(*Duration) + return arrayEqualDuration(l, r) + case *Map: + r := right.(*Map) + if opt.unorderedMapKeys { + return arrayApproxEqualMap(l, r, opt) + } + return arrayApproxEqualList(l.List, r.List, opt) + case *Dictionary: + r := right.(*Dictionary) + return arrayApproxEqualDict(l, r, opt) + case ExtensionArray: + r := right.(ExtensionArray) + return arrayApproxEqualExtension(l, r, opt) + case *SparseUnion: + r := right.(*SparseUnion) + return arraySparseUnionApproxEqual(l, r, opt) + case *DenseUnion: + r := right.(*DenseUnion) + return arrayDenseUnionApproxEqual(l, r, opt) + case *RunEndEncoded: + r := right.(*RunEndEncoded) + return arrayRunEndEncodedApproxEqual(l, r, opt) + default: + panic(fmt.Errorf("arrow/array: unknown array type %T", l)) + } +} + +func baseArrayEqual(left, right arrow.Array) bool { + switch { + case left.Len() != right.Len(): + return false + case left.NullN() != right.NullN(): + return false + case !arrow.TypeEqual(left.DataType(), right.DataType()): // We do not check for metadata as in the C++ implementation. + return false + case !validityBitmapEqual(left, right): + return false + } + return true +} + +func validityBitmapEqual(left, right arrow.Array) bool { + // TODO(alexandreyc): make it faster by comparing byte slices of the validity bitmap? + n := left.Len() + if n != right.Len() { + return false + } + for i := 0; i < n; i++ { + if left.IsNull(i) != right.IsNull(i) { + return false + } + } + return true +} + +func arrayApproxEqualFloat16(left, right *Float16, opt equalOption) bool { + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + if !opt.f16(left.Value(i), right.Value(i)) { + return false + } + } + return true +} + +func arrayApproxEqualFloat32(left, right *Float32, opt equalOption) bool { + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + if !opt.f32(left.Value(i), right.Value(i)) { + return false + } + } + return true +} + +func arrayApproxEqualFloat64(left, right *Float64, opt equalOption) bool { + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + if !opt.f64(left.Value(i), right.Value(i)) { + return false + } + } + return true +} + +func arrayApproxEqualList(left, right *List, opt equalOption) bool { + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + o := func() bool { + l := left.newListValue(i) + defer l.Release() + r := right.newListValue(i) + defer r.Release() + return arrayApproxEqual(l, r, opt) + }() + if !o { + return false + } + } + return true +} + +func arrayApproxEqualLargeList(left, right *LargeList, opt equalOption) bool { + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + o := func() bool { + l := left.newListValue(i) + defer l.Release() + r := right.newListValue(i) + defer r.Release() + return arrayApproxEqual(l, r, opt) + }() + if !o { + return false + } + } + return true +} + +func arrayApproxEqualListView(left, right *ListView, opt equalOption) bool { + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + o := func() bool { + l := left.newListValue(i) + defer l.Release() + r := right.newListValue(i) + defer r.Release() + return arrayApproxEqual(l, r, opt) + }() + if !o { + return false + } + } + return true +} + +func arrayApproxEqualLargeListView(left, right *LargeListView, opt equalOption) bool { + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + o := func() bool { + l := left.newListValue(i) + defer l.Release() + r := right.newListValue(i) + defer r.Release() + return arrayApproxEqual(l, r, opt) + }() + if !o { + return false + } + } + return true +} + +func arrayApproxEqualFixedSizeList(left, right *FixedSizeList, opt equalOption) bool { + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + o := func() bool { + l := left.newListValue(i) + defer l.Release() + r := right.newListValue(i) + defer r.Release() + return arrayApproxEqual(l, r, opt) + }() + if !o { + return false + } + } + return true +} + +func arrayApproxEqualStruct(left, right *Struct, opt equalOption) bool { + return bitutils.VisitSetBitRuns( + left.NullBitmapBytes(), + int64(left.Offset()), int64(left.Len()), + approxEqualStructRun(left, right, opt), + ) == nil +} + +func approxEqualStructRun(left, right *Struct, opt equalOption) bitutils.VisitFn { + return func(pos int64, length int64) error { + for i := range left.fields { + if !sliceApproxEqual(left.fields[i], pos, pos+length, right.fields[i], pos, pos+length, opt) { + return arrow.ErrInvalid + } + } + return nil + } +} + +// arrayApproxEqualMap doesn't care about the order of keys (in Go map traversal order is undefined) +func arrayApproxEqualMap(left, right *Map, opt equalOption) bool { + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + if !arrayApproxEqualSingleMapEntry(left.newListValue(i).(*Struct), right.newListValue(i).(*Struct), opt) { + return false + } + } + return true +} + +// arrayApproxEqualSingleMapEntry is a helper function that checks if a single entry pair is approx equal. +// Basically, it doesn't care about key order. +// structs passed will be released +func arrayApproxEqualSingleMapEntry(left, right *Struct, opt equalOption) bool { + defer left.Release() + defer right.Release() + + // we don't compare the validity bitmap, but we want other checks from baseArrayEqual + switch { + case left.Len() != right.Len(): + return false + case left.NullN() != right.NullN(): + return false + case !arrow.TypeEqual(left.DataType(), right.DataType()): // We do not check for metadata as in the C++ implementation. + return false + case left.NullN() == left.Len(): + return true + } + + used := make(map[int]bool, right.Len()) + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + + found := false + lBeg, lEnd := int64(i), int64(i+1) + for j := 0; j < right.Len(); j++ { + if used[j] { + continue + } + if right.IsNull(j) { + used[j] = true + continue + } + + rBeg, rEnd := int64(j), int64(j+1) + + // check keys (field 0) + if !sliceApproxEqual(left.Field(0), lBeg, lEnd, right.Field(0), rBeg, rEnd, opt) { + continue + } + + // only now check the values + if sliceApproxEqual(left.Field(1), lBeg, lEnd, right.Field(1), rBeg, rEnd, opt) { + found = true + used[j] = true + break + } + } + if !found { + return false + } + } + + return len(used) == right.Len() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array/concat.go b/vendor/github.com/apache/arrow/go/v14/arrow/array/concat.go new file mode 100644 index 000000000..9d815023c --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array/concat.go @@ -0,0 +1,910 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package array + +import ( + "errors" + "fmt" + "math" + "math/bits" + "unsafe" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/bitutil" + "github.com/apache/arrow/go/v14/arrow/encoded" + "github.com/apache/arrow/go/v14/arrow/internal/debug" + "github.com/apache/arrow/go/v14/arrow/memory" + "github.com/apache/arrow/go/v14/internal/bitutils" + "github.com/apache/arrow/go/v14/internal/utils" +) + +// Concatenate creates a new arrow.Array which is the concatenation of the +// passed in arrays. Returns nil if an error is encountered. +// +// The passed in arrays still need to be released manually, and will not be +// released by this function. +func Concatenate(arrs []arrow.Array, mem memory.Allocator) (result arrow.Array, err error) { + if len(arrs) == 0 { + return nil, errors.New("array/concat: must pass at least one array") + } + + // gather Data of inputs + data := make([]arrow.ArrayData, len(arrs)) + for i, ar := range arrs { + if !arrow.TypeEqual(ar.DataType(), arrs[0].DataType()) { + return nil, fmt.Errorf("arrays to be concatenated must be identically typed, but %s and %s were encountered", + arrs[0].DataType(), ar.DataType()) + } + data[i] = ar.Data() + } + + out, err := concat(data, mem) + if err != nil { + return nil, err + } + + defer out.Release() + return MakeFromData(out), nil +} + +// simple struct to hold ranges +type rng struct { + offset, len int +} + +// simple bitmap struct to reference a specific slice of a bitmap where the range +// offset and length are in bits +type bitmap struct { + data []byte + rng rng +} + +// gather up the bitmaps from the passed in data objects +func gatherBitmaps(data []arrow.ArrayData, idx int) []bitmap { + out := make([]bitmap, len(data)) + for i, d := range data { + if d.Buffers()[idx] != nil { + out[i].data = d.Buffers()[idx].Bytes() + } + out[i].rng.offset = d.Offset() + out[i].rng.len = d.Len() + } + return out +} + +// gatherFixedBuffers gathers up the buffer objects of the given index, specifically +// returning only the slices of the buffers which are relevant to the passed in arrays +// in case they are themselves slices of other arrays. nil buffers are ignored and not +// in the output slice. +func gatherFixedBuffers(data []arrow.ArrayData, idx, byteWidth int) []*memory.Buffer { + out := make([]*memory.Buffer, 0, len(data)) + for _, d := range data { + buf := d.Buffers()[idx] + if buf == nil { + continue + } + + out = append(out, memory.NewBufferBytes(buf.Bytes()[d.Offset()*byteWidth:(d.Offset()+d.Len())*byteWidth])) + } + return out +} + +// gatherBuffersFixedWidthType is like gatherFixedBuffers, but uses a datatype to determine the size +// to use for determining the byte slice rather than a passed in bytewidth. +func gatherBuffersFixedWidthType(data []arrow.ArrayData, idx int, fixed arrow.FixedWidthDataType) []*memory.Buffer { + return gatherFixedBuffers(data, idx, fixed.BitWidth()/8) +} + +// gatherBufferRanges requires that len(ranges) == len(data) and returns a list of buffers +// which represent the corresponding range of each buffer in the specified index of each +// data object. +func gatherBufferRanges(data []arrow.ArrayData, idx int, ranges []rng) []*memory.Buffer { + out := make([]*memory.Buffer, 0, len(data)) + for i, d := range data { + buf := d.Buffers()[idx] + if buf == nil { + debug.Assert(ranges[i].len == 0, "misaligned buffer value ranges") + continue + } + + out = append(out, memory.NewBufferBytes(buf.Bytes()[ranges[i].offset:ranges[i].offset+ranges[i].len])) + } + return out +} + +// gatherChildren gathers the children data objects for child of index idx for all of the data objects. +func gatherChildren(data []arrow.ArrayData, idx int) []arrow.ArrayData { + return gatherChildrenMultiplier(data, idx, 1) +} + +// gatherChildrenMultiplier gathers the full data slice of the underlying values from the children data objects +// such as the values data for a list array so that it can return a slice of the buffer for a given +// index into the children. +func gatherChildrenMultiplier(data []arrow.ArrayData, idx, multiplier int) []arrow.ArrayData { + out := make([]arrow.ArrayData, len(data)) + for i, d := range data { + out[i] = NewSliceData(d.Children()[idx], int64(d.Offset()*multiplier), int64(d.Offset()+d.Len())*int64(multiplier)) + } + return out +} + +// gatherChildrenRanges returns a slice of Data objects which each represent slices of the given ranges from the +// child in the specified index from each data object. +func gatherChildrenRanges(data []arrow.ArrayData, idx int, ranges []rng) []arrow.ArrayData { + debug.Assert(len(data) == len(ranges), "mismatched children ranges for concat") + out := make([]arrow.ArrayData, len(data)) + for i, d := range data { + out[i] = NewSliceData(d.Children()[idx], int64(ranges[i].offset), int64(ranges[i].offset+ranges[i].len)) + } + return out +} + +// creates a single contiguous buffer which contains the concatenation of all of the passed +// in buffer objects. +func concatBuffers(bufs []*memory.Buffer, mem memory.Allocator) *memory.Buffer { + outLen := 0 + for _, b := range bufs { + outLen += b.Len() + } + out := memory.NewResizableBuffer(mem) + out.Resize(outLen) + + data := out.Bytes() + for _, b := range bufs { + copy(data, b.Bytes()) + data = data[b.Len():] + } + return out +} + +func handle32BitOffsets(outLen int, buffers []*memory.Buffer, out *memory.Buffer) (*memory.Buffer, []rng, error) { + dst := arrow.Int32Traits.CastFromBytes(out.Bytes()) + valuesRanges := make([]rng, len(buffers)) + nextOffset := int32(0) + nextElem := int(0) + for i, b := range buffers { + if b.Len() == 0 { + valuesRanges[i].offset = 0 + valuesRanges[i].len = 0 + continue + } + + // when we gather our buffers, we sliced off the last offset from the buffer + // so that we could count the lengths accurately + src := arrow.Int32Traits.CastFromBytes(b.Bytes()) + valuesRanges[i].offset = int(src[0]) + // expand our slice to see that final offset + expand := src[:len(src)+1] + // compute the length of this range by taking the final offset and subtracting where we started. + valuesRanges[i].len = int(expand[len(src)]) - valuesRanges[i].offset + + if nextOffset > math.MaxInt32-int32(valuesRanges[i].len) { + return nil, nil, errors.New("offset overflow while concatenating arrays") + } + + // adjust each offset by the difference between our last ending point and our starting point + adj := nextOffset - src[0] + for j, o := range src { + dst[nextElem+j] = adj + o + } + + // the next index for an element in the output buffer + nextElem += b.Len() / arrow.Int32SizeBytes + // update our offset counter to be the total current length of our output + nextOffset += int32(valuesRanges[i].len) + } + + // final offset should point to the end of the data + dst[outLen] = nextOffset + return out, valuesRanges, nil +} + +func unifyDictionaries(mem memory.Allocator, data []arrow.ArrayData, dt *arrow.DictionaryType) ([]*memory.Buffer, arrow.Array, error) { + unifier, err := NewDictionaryUnifier(mem, dt.ValueType) + if err != nil { + return nil, nil, err + } + defer unifier.Release() + + newLookup := make([]*memory.Buffer, len(data)) + for i, d := range data { + dictArr := MakeFromData(d.Dictionary()) + defer dictArr.Release() + newLookup[i], err = unifier.UnifyAndTranspose(dictArr) + if err != nil { + return nil, nil, err + } + } + + unified, err := unifier.GetResultWithIndexType(dt.IndexType) + if err != nil { + for _, b := range newLookup { + b.Release() + } + return nil, nil, err + } + return newLookup, unified, nil +} + +func concatDictIndices(mem memory.Allocator, data []arrow.ArrayData, idxType arrow.FixedWidthDataType, transpositions []*memory.Buffer) (out *memory.Buffer, err error) { + defer func() { + if err != nil && out != nil { + out.Release() + out = nil + } + }() + + idxWidth := idxType.BitWidth() / 8 + outLen := 0 + for i, d := range data { + outLen += d.Len() + defer transpositions[i].Release() + } + + out = memory.NewResizableBuffer(mem) + out.Resize(outLen * idxWidth) + + outData := out.Bytes() + for i, d := range data { + transposeMap := arrow.Int32Traits.CastFromBytes(transpositions[i].Bytes()) + src := d.Buffers()[1].Bytes() + if d.Buffers()[0] == nil { + if err = utils.TransposeIntsBuffers(idxType, idxType, src, outData, d.Offset(), 0, d.Len(), transposeMap); err != nil { + return + } + } else { + rdr := bitutils.NewBitRunReader(d.Buffers()[0].Bytes(), int64(d.Offset()), int64(d.Len())) + pos := 0 + for { + run := rdr.NextRun() + if run.Len == 0 { + break + } + + if run.Set { + err = utils.TransposeIntsBuffers(idxType, idxType, src, outData, d.Offset()+pos, pos, int(run.Len), transposeMap) + if err != nil { + return + } + } else { + memory.Set(outData[pos:pos+(int(run.Len)*idxWidth)], 0x00) + } + + pos += int(run.Len) + } + } + outData = outData[d.Len()*idxWidth:] + } + return +} + +func handle64BitOffsets(outLen int, buffers []*memory.Buffer, out *memory.Buffer) (*memory.Buffer, []rng, error) { + dst := arrow.Int64Traits.CastFromBytes(out.Bytes()) + valuesRanges := make([]rng, len(buffers)) + nextOffset := int64(0) + nextElem := int(0) + for i, b := range buffers { + if b.Len() == 0 { + valuesRanges[i].offset = 0 + valuesRanges[i].len = 0 + continue + } + + // when we gather our buffers, we sliced off the last offset from the buffer + // so that we could count the lengths accurately + src := arrow.Int64Traits.CastFromBytes(b.Bytes()) + valuesRanges[i].offset = int(src[0]) + // expand our slice to see that final offset + expand := src[:len(src)+1] + // compute the length of this range by taking the final offset and subtracting where we started. + valuesRanges[i].len = int(expand[len(src)]) - valuesRanges[i].offset + + if nextOffset > math.MaxInt64-int64(valuesRanges[i].len) { + return nil, nil, errors.New("offset overflow while concatenating arrays") + } + + // adjust each offset by the difference between our last ending point and our starting point + adj := nextOffset - src[0] + for j, o := range src { + dst[nextElem+j] = adj + o + } + + // the next index for an element in the output buffer + nextElem += b.Len() / arrow.Int64SizeBytes + // update our offset counter to be the total current length of our output + nextOffset += int64(valuesRanges[i].len) + } + + // final offset should point to the end of the data + dst[outLen] = nextOffset + return out, valuesRanges, nil +} + +// concatOffsets creates a single offset buffer which represents the concatenation of all of the +// offsets buffers, adjusting the offsets appropriately to their new relative locations. +// +// It also returns the list of ranges that need to be fetched for the corresponding value buffers +// to construct the final concatenated value buffer. +func concatOffsets(buffers []*memory.Buffer, byteWidth int, mem memory.Allocator) (*memory.Buffer, []rng, error) { + outLen := 0 + for _, b := range buffers { + outLen += b.Len() / byteWidth + } + + out := memory.NewResizableBuffer(mem) + out.Resize(byteWidth * (outLen + 1)) + + switch byteWidth { + case arrow.Int64SizeBytes: + return handle64BitOffsets(outLen, buffers, out) + default: + return handle32BitOffsets(outLen, buffers, out) + } +} + +func sumArraySizes(data []arrow.ArrayData) int { + outSize := 0 + for _, arr := range data { + outSize += arr.Len() + } + return outSize +} + +func getListViewBufferValues[T int32 | int64](data arrow.ArrayData, i int) []T { + bytes := data.Buffers()[i].Bytes() + base := (*T)(unsafe.Pointer(&bytes[0])) + ret := unsafe.Slice(base, data.Offset()+data.Len()) + return ret[data.Offset():] +} + +func putListViewOffsets32(in arrow.ArrayData, displacement int32, out *memory.Buffer, outOff int) { + debug.Assert(in.DataType().ID() == arrow.LIST_VIEW, "putListViewOffsets32: expected LIST_VIEW data") + inOff, inLen := in.Offset(), in.Len() + if inLen == 0 { + return + } + bitmap := in.Buffers()[0] + srcOffsets := getListViewBufferValues[int32](in, 1) + srcSizes := getListViewBufferValues[int32](in, 2) + isValidAndNonEmpty := func(i int) bool { + return (bitmap == nil || bitutil.BitIsSet(bitmap.Bytes(), inOff+i)) && srcSizes[i] > 0 + } + + dstOffsets := arrow.Int32Traits.CastFromBytes(out.Bytes()) + for i, offset := range srcOffsets { + if isValidAndNonEmpty(i) { + // This is guaranteed by RangeOfValuesUsed returning the smallest offset + // of valid and non-empty list-views. + debug.Assert(offset+displacement >= 0, "putListViewOffsets32: offset underflow while concatenating arrays") + dstOffsets[outOff+i] = offset + displacement + } else { + dstOffsets[outOff+i] = 0 + } + } +} + +func putListViewOffsets64(in arrow.ArrayData, displacement int64, out *memory.Buffer, outOff int) { + debug.Assert(in.DataType().ID() == arrow.LARGE_LIST_VIEW, "putListViewOffsets64: expected LARGE_LIST_VIEW data") + inOff, inLen := in.Offset(), in.Len() + if inLen == 0 { + return + } + bitmap := in.Buffers()[0] + srcOffsets := getListViewBufferValues[int64](in, 1) + srcSizes := getListViewBufferValues[int64](in, 2) + isValidAndNonEmpty := func(i int) bool { + return (bitmap == nil || bitutil.BitIsSet(bitmap.Bytes(), inOff+i)) && srcSizes[i] > 0 + } + + dstOffsets := arrow.Int64Traits.CastFromBytes(out.Bytes()) + for i, offset := range srcOffsets { + if isValidAndNonEmpty(i) { + // This is guaranteed by RangeOfValuesUsed returning the smallest offset + // of valid and non-empty list-views. + debug.Assert(offset+displacement >= 0, "putListViewOffsets64: offset underflow while concatenating arrays") + dstOffsets[outOff+i] = offset + displacement + } else { + dstOffsets[outOff+i] = 0 + } + } +} + +// Concatenate buffers holding list-view offsets into a single buffer of offsets +// +// valueRanges contains the relevant ranges of values in the child array actually +// referenced to by the views. Most commonly, these ranges will start from 0, +// but when that is not the case, we need to adjust the displacement of offsets. +// The concatenated child array does not contain values from the beginning +// if they are not referenced to by any view. +func concatListViewOffsets(data []arrow.ArrayData, byteWidth int, valueRanges []rng, mem memory.Allocator) (*memory.Buffer, error) { + outSize := sumArraySizes(data) + if byteWidth == 4 && outSize > math.MaxInt32 { + return nil, fmt.Errorf("%w: offset overflow while concatenating arrays", arrow.ErrInvalid) + } + out := memory.NewResizableBuffer(mem) + out.Resize(byteWidth * outSize) + + numChildValues, elementsLength := 0, 0 + for i, arr := range data { + displacement := numChildValues - valueRanges[i].offset + if byteWidth == 4 { + putListViewOffsets32(arr, int32(displacement), out, elementsLength) + } else { + putListViewOffsets64(arr, int64(displacement), out, elementsLength) + } + elementsLength += arr.Len() + numChildValues += valueRanges[i].len + } + debug.Assert(elementsLength == outSize, "implementation error") + + return out, nil +} + +func zeroNullListViewSizes[T int32 | int64](data arrow.ArrayData) { + if data.Len() == 0 || data.Buffers()[0] == nil { + return + } + validity := data.Buffers()[0].Bytes() + sizes := getListViewBufferValues[T](data, 2) + + for i := 0; i < data.Len(); i++ { + if !bitutil.BitIsSet(validity, data.Offset()+i) { + sizes[i] = 0 + } + } +} + +func concatListView(data []arrow.ArrayData, offsetType arrow.FixedWidthDataType, out *Data, mem memory.Allocator) (err error) { + // Calculate the ranges of values that each list-view array uses + valueRanges := make([]rng, len(data)) + for i, input := range data { + offset, len := rangeOfValuesUsed(input) + valueRanges[i].offset = offset + valueRanges[i].len = len + } + + // Gather the children ranges of each input array + childData := gatherChildrenRanges(data, 0, valueRanges) + for _, c := range childData { + defer c.Release() + } + + // Concatenate the values + values, err := concat(childData, mem) + if err != nil { + return err + } + + // Concatenate the offsets + offsetBuffer, err := concatListViewOffsets(data, offsetType.Bytes(), valueRanges, mem) + if err != nil { + return err + } + + // Concatenate the sizes + sizeBuffers := gatherBuffersFixedWidthType(data, 2, offsetType) + sizeBuffer := concatBuffers(sizeBuffers, mem) + + out.childData = []arrow.ArrayData{values} + out.buffers[1] = offsetBuffer + out.buffers[2] = sizeBuffer + + // To make sure the sizes don't reference values that are not in the new + // concatenated values array, we zero the sizes of null list-view values. + if offsetType.ID() == arrow.INT32 { + zeroNullListViewSizes[int32](out) + } else { + zeroNullListViewSizes[int64](out) + } + + return nil +} + +// concat is the implementation for actually performing the concatenation of the arrow.ArrayData +// objects that we can call internally for nested types. +func concat(data []arrow.ArrayData, mem memory.Allocator) (arr arrow.ArrayData, err error) { + out := &Data{refCount: 1, dtype: data[0].DataType(), nulls: 0} + defer func() { + if pErr := recover(); pErr != nil { + switch e := pErr.(type) { + case error: + err = fmt.Errorf("arrow/concat: %w", e) + default: + err = fmt.Errorf("arrow/concat: %v", pErr) + } + } + if err != nil { + out.Release() + } + }() + for _, d := range data { + out.length += d.Len() + if out.nulls == UnknownNullCount || d.NullN() == UnknownNullCount { + out.nulls = UnknownNullCount + continue + } + out.nulls += d.NullN() + } + + out.buffers = make([]*memory.Buffer, len(data[0].Buffers())) + if out.nulls != 0 && out.dtype.ID() != arrow.NULL { + bm, err := concatBitmaps(gatherBitmaps(data, 0), mem) + if err != nil { + return nil, err + } + out.buffers[0] = bm + } + + dt := out.dtype + if dt.ID() == arrow.EXTENSION { + dt = dt.(arrow.ExtensionType).StorageType() + } + + switch dt := dt.(type) { + case *arrow.NullType: + case *arrow.BooleanType: + bm, err := concatBitmaps(gatherBitmaps(data, 1), mem) + if err != nil { + return nil, err + } + out.buffers[1] = bm + case *arrow.DictionaryType: + idxType := dt.IndexType.(arrow.FixedWidthDataType) + // two cases: all dictionaries are the same or we need to unify them + dictsSame := true + dict0 := MakeFromData(data[0].Dictionary()) + defer dict0.Release() + for _, d := range data { + dict := MakeFromData(d.Dictionary()) + if !Equal(dict0, dict) { + dict.Release() + dictsSame = false + break + } + dict.Release() + } + + indexBuffers := gatherBuffersFixedWidthType(data, 1, idxType) + if dictsSame { + out.dictionary = dict0.Data().(*Data) + out.dictionary.Retain() + out.buffers[1] = concatBuffers(indexBuffers, mem) + break + } + + indexLookup, unifiedDict, err := unifyDictionaries(mem, data, dt) + if err != nil { + return nil, err + } + defer unifiedDict.Release() + out.dictionary = unifiedDict.Data().(*Data) + out.dictionary.Retain() + + out.buffers[1], err = concatDictIndices(mem, data, idxType, indexLookup) + if err != nil { + return nil, err + } + case arrow.FixedWidthDataType: + out.buffers[1] = concatBuffers(gatherBuffersFixedWidthType(data, 1, dt), mem) + case arrow.BinaryDataType: + offsetWidth := dt.Layout().Buffers[1].ByteWidth + offsetBuffer, valueRanges, err := concatOffsets(gatherFixedBuffers(data, 1, offsetWidth), offsetWidth, mem) + if err != nil { + return nil, err + } + out.buffers[1] = offsetBuffer + out.buffers[2] = concatBuffers(gatherBufferRanges(data, 2, valueRanges), mem) + case *arrow.ListType: + offsetWidth := dt.Layout().Buffers[1].ByteWidth + offsetBuffer, valueRanges, err := concatOffsets(gatherFixedBuffers(data, 1, offsetWidth), offsetWidth, mem) + if err != nil { + return nil, err + } + childData := gatherChildrenRanges(data, 0, valueRanges) + for _, c := range childData { + defer c.Release() + } + + out.buffers[1] = offsetBuffer + out.childData = make([]arrow.ArrayData, 1) + out.childData[0], err = concat(childData, mem) + if err != nil { + return nil, err + } + case *arrow.LargeListType: + offsetWidth := dt.Layout().Buffers[1].ByteWidth + offsetBuffer, valueRanges, err := concatOffsets(gatherFixedBuffers(data, 1, offsetWidth), offsetWidth, mem) + if err != nil { + return nil, err + } + childData := gatherChildrenRanges(data, 0, valueRanges) + for _, c := range childData { + defer c.Release() + } + + out.buffers[1] = offsetBuffer + out.childData = make([]arrow.ArrayData, 1) + out.childData[0], err = concat(childData, mem) + if err != nil { + return nil, err + } + case *arrow.ListViewType: + offsetType := arrow.PrimitiveTypes.Int32.(arrow.FixedWidthDataType) + err := concatListView(data, offsetType, out, mem) + if err != nil { + return nil, err + } + case *arrow.LargeListViewType: + offsetType := arrow.PrimitiveTypes.Int64.(arrow.FixedWidthDataType) + err := concatListView(data, offsetType, out, mem) + if err != nil { + return nil, err + } + case *arrow.FixedSizeListType: + childData := gatherChildrenMultiplier(data, 0, int(dt.Len())) + for _, c := range childData { + defer c.Release() + } + + children, err := concat(childData, mem) + if err != nil { + return nil, err + } + out.childData = []arrow.ArrayData{children} + case *arrow.StructType: + out.childData = make([]arrow.ArrayData, len(dt.Fields())) + for i := range dt.Fields() { + children := gatherChildren(data, i) + for _, c := range children { + defer c.Release() + } + + childData, err := concat(children, mem) + if err != nil { + return nil, err + } + out.childData[i] = childData + } + case *arrow.MapType: + offsetWidth := dt.Layout().Buffers[1].ByteWidth + offsetBuffer, valueRanges, err := concatOffsets(gatherFixedBuffers(data, 1, offsetWidth), offsetWidth, mem) + if err != nil { + return nil, err + } + childData := gatherChildrenRanges(data, 0, valueRanges) + for _, c := range childData { + defer c.Release() + } + + out.buffers[1] = offsetBuffer + out.childData = make([]arrow.ArrayData, 1) + out.childData[0], err = concat(childData, mem) + if err != nil { + return nil, err + } + case *arrow.RunEndEncodedType: + physicalLength, overflow := int(0), false + // we can't use gatherChildren because the Offset and Len of + // data doesn't correspond to the physical length or offset + runs := make([]arrow.ArrayData, len(data)) + values := make([]arrow.ArrayData, len(data)) + for i, d := range data { + plen := encoded.GetPhysicalLength(d) + off := encoded.FindPhysicalOffset(d) + + runs[i] = NewSliceData(d.Children()[0], int64(off), int64(off+plen)) + defer runs[i].Release() + values[i] = NewSliceData(d.Children()[1], int64(off), int64(off+plen)) + defer values[i].Release() + + physicalLength, overflow = addOvf(physicalLength, plen) + if overflow { + return nil, fmt.Errorf("%w: run end encoded array length must fit into a 32-bit signed integer", + arrow.ErrInvalid) + } + } + + runEndsByteWidth := runs[0].DataType().(arrow.FixedWidthDataType).Bytes() + runEndsBuffers := gatherFixedBuffers(runs, 1, runEndsByteWidth) + outRunEndsLen := physicalLength * runEndsByteWidth + outRunEndsBuf := memory.NewResizableBuffer(mem) + outRunEndsBuf.Resize(outRunEndsLen) + defer outRunEndsBuf.Release() + + if err := updateRunEnds(runEndsByteWidth, data, runEndsBuffers, outRunEndsBuf); err != nil { + return nil, err + } + + out.childData = make([]arrow.ArrayData, 2) + out.childData[0] = NewData(data[0].Children()[0].DataType(), int(physicalLength), + []*memory.Buffer{nil, outRunEndsBuf}, nil, 0, 0) + + var err error + out.childData[1], err = concat(values, mem) + if err != nil { + out.childData[0].Release() + return nil, err + } + + default: + return nil, fmt.Errorf("concatenate not implemented for type %s", dt) + } + + return out, nil +} + +// check overflow in the addition, taken from bits.Add but adapted for signed integers +// rather than unsigned integers. bits.UintSize will be either 32 or 64 based on +// whether our architecture is 32 bit or 64. The operation is the same for both cases, +// the only difference is how much we need to shift by 30 for 32 bit and 62 for 64 bit. +// Thus, bits.UintSize - 2 is how much we shift right by to check if we had an overflow +// in the signed addition. +// +// First return is the result of the sum, the second return is true if there was an overflow +func addOvf(x, y int) (int, bool) { + sum := x + y + return sum, ((x&y)|((x|y)&^sum))>>(bits.UintSize-2) == 1 +} + +// concatenate bitmaps together and return a buffer with the combined bitmaps +func concatBitmaps(bitmaps []bitmap, mem memory.Allocator) (*memory.Buffer, error) { + var ( + outlen int + overflow bool + ) + + for _, bm := range bitmaps { + if outlen, overflow = addOvf(outlen, bm.rng.len); overflow { + return nil, errors.New("length overflow when concatenating arrays") + } + } + + out := memory.NewResizableBuffer(mem) + out.Resize(int(bitutil.BytesForBits(int64(outlen)))) + dst := out.Bytes() + + offset := 0 + for _, bm := range bitmaps { + if bm.data == nil { // if the bitmap is nil, that implies that the value is true for all elements + bitutil.SetBitsTo(out.Bytes(), int64(offset), int64(bm.rng.len), true) + } else { + bitutil.CopyBitmap(bm.data, bm.rng.offset, bm.rng.len, dst, offset) + } + offset += bm.rng.len + } + return out, nil +} + +func updateRunEnds(byteWidth int, inputData []arrow.ArrayData, inputBuffers []*memory.Buffer, outputBuffer *memory.Buffer) error { + switch byteWidth { + case 2: + out := arrow.Int16Traits.CastFromBytes(outputBuffer.Bytes()) + return updateRunsInt16(inputData, inputBuffers, out) + case 4: + out := arrow.Int32Traits.CastFromBytes(outputBuffer.Bytes()) + return updateRunsInt32(inputData, inputBuffers, out) + case 8: + out := arrow.Int64Traits.CastFromBytes(outputBuffer.Bytes()) + return updateRunsInt64(inputData, inputBuffers, out) + } + return fmt.Errorf("%w: invalid dataType for RLE runEnds", arrow.ErrInvalid) +} + +func updateRunsInt16(inputData []arrow.ArrayData, inputBuffers []*memory.Buffer, output []int16) error { + // for now we will not attempt to optimize by checking if we + // can fold the end and beginning of each array we're concatenating + // into a single run + pos := 0 + for i, buf := range inputBuffers { + if buf.Len() == 0 { + continue + } + src := arrow.Int16Traits.CastFromBytes(buf.Bytes()) + if pos == 0 { + pos += copy(output, src) + continue + } + + lastEnd := output[pos-1] + // we can check the last runEnd in the src and add it to the + // last value that we're adjusting them all by to see if we + // are going to overflow + if int64(lastEnd)+int64(int(src[len(src)-1])-inputData[i].Offset()) > math.MaxInt16 { + return fmt.Errorf("%w: overflow in run-length-encoded run ends concat", arrow.ErrInvalid) + } + + // adjust all of the run ends by first normalizing them (e - data[i].offset) + // then adding the previous value we ended on. Since the offset + // is a logical length offset it should be accurate to just subtract + // it from each value. + for j, e := range src { + output[pos+j] = lastEnd + int16(int(e)-inputData[i].Offset()) + } + pos += len(src) + } + return nil +} + +func updateRunsInt32(inputData []arrow.ArrayData, inputBuffers []*memory.Buffer, output []int32) error { + // for now we will not attempt to optimize by checking if we + // can fold the end and beginning of each array we're concatenating + // into a single run + pos := 0 + for i, buf := range inputBuffers { + if buf.Len() == 0 { + continue + } + src := arrow.Int32Traits.CastFromBytes(buf.Bytes()) + if pos == 0 { + pos += copy(output, src) + continue + } + + lastEnd := output[pos-1] + // we can check the last runEnd in the src and add it to the + // last value that we're adjusting them all by to see if we + // are going to overflow + if int64(lastEnd)+int64(int(src[len(src)-1])-inputData[i].Offset()) > math.MaxInt32 { + return fmt.Errorf("%w: overflow in run-length-encoded run ends concat", arrow.ErrInvalid) + } + + // adjust all of the run ends by first normalizing them (e - data[i].offset) + // then adding the previous value we ended on. Since the offset + // is a logical length offset it should be accurate to just subtract + // it from each value. + for j, e := range src { + output[pos+j] = lastEnd + int32(int(e)-inputData[i].Offset()) + } + pos += len(src) + } + return nil +} + +func updateRunsInt64(inputData []arrow.ArrayData, inputBuffers []*memory.Buffer, output []int64) error { + // for now we will not attempt to optimize by checking if we + // can fold the end and beginning of each array we're concatenating + // into a single run + pos := 0 + for i, buf := range inputBuffers { + if buf.Len() == 0 { + continue + } + src := arrow.Int64Traits.CastFromBytes(buf.Bytes()) + if pos == 0 { + pos += copy(output, src) + continue + } + + lastEnd := output[pos-1] + // we can check the last runEnd in the src and add it to the + // last value that we're adjusting them all by to see if we + // are going to overflow + if uint64(lastEnd)+uint64(int(src[len(src)-1])-inputData[i].Offset()) > math.MaxInt64 { + return fmt.Errorf("%w: overflow in run-length-encoded run ends concat", arrow.ErrInvalid) + } + + // adjust all of the run ends by first normalizing them (e - data[i].offset) + // then adding the previous value we ended on. Since the offset + // is a logical length offset it should be accurate to just subtract + // it from each value. + for j, e := range src { + output[pos+j] = lastEnd + e - int64(inputData[i].Offset()) + } + pos += len(src) + } + return nil +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array/data.go b/vendor/github.com/apache/arrow/go/v14/arrow/array/data.go new file mode 100644 index 000000000..49df06fb1 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array/data.go @@ -0,0 +1,250 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package array + +import ( + "hash/maphash" + "math/bits" + "sync/atomic" + "unsafe" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/internal/debug" + "github.com/apache/arrow/go/v14/arrow/memory" +) + +// Data represents the memory and metadata of an Arrow array. +type Data struct { + refCount int64 + dtype arrow.DataType + nulls int + offset int + length int + + // for dictionary arrays: buffers will be the null validity bitmap and the indexes that reference + // values in the dictionary member. childData would be empty in a dictionary array + buffers []*memory.Buffer // TODO(sgc): should this be an interface? + childData []arrow.ArrayData // TODO(sgc): managed by ListArray, StructArray and UnionArray types + dictionary *Data // only populated for dictionary arrays +} + +// NewData creates a new Data. +func NewData(dtype arrow.DataType, length int, buffers []*memory.Buffer, childData []arrow.ArrayData, nulls, offset int) *Data { + for _, b := range buffers { + if b != nil { + b.Retain() + } + } + + for _, child := range childData { + if child != nil { + child.Retain() + } + } + + return &Data{ + refCount: 1, + dtype: dtype, + nulls: nulls, + length: length, + offset: offset, + buffers: buffers, + childData: childData, + } +} + +// NewDataWithDictionary creates a new data object, but also sets the provided dictionary into the data if it's not nil +func NewDataWithDictionary(dtype arrow.DataType, length int, buffers []*memory.Buffer, nulls, offset int, dict *Data) *Data { + data := NewData(dtype, length, buffers, nil, nulls, offset) + if dict != nil { + dict.Retain() + } + data.dictionary = dict + return data +} + +func (d *Data) Copy() *Data { + // don't pass the slices directly, otherwise it retains the connection + // we need to make new slices and populate them with the same pointers + bufs := make([]*memory.Buffer, len(d.buffers)) + copy(bufs, d.buffers) + children := make([]arrow.ArrayData, len(d.childData)) + copy(children, d.childData) + + data := NewData(d.dtype, d.length, bufs, children, d.nulls, d.offset) + data.SetDictionary(d.dictionary) + return data +} + +// Reset sets the Data for re-use. +func (d *Data) Reset(dtype arrow.DataType, length int, buffers []*memory.Buffer, childData []arrow.ArrayData, nulls, offset int) { + // Retain new buffers before releasing existing buffers in-case they're the same ones to prevent accidental premature + // release. + for _, b := range buffers { + if b != nil { + b.Retain() + } + } + for _, b := range d.buffers { + if b != nil { + b.Release() + } + } + d.buffers = buffers + + // Retain new children data before releasing existing children data in-case they're the same ones to prevent accidental + // premature release. + for _, d := range childData { + if d != nil { + d.Retain() + } + } + for _, d := range d.childData { + if d != nil { + d.Release() + } + } + d.childData = childData + + d.dtype = dtype + d.length = length + d.nulls = nulls + d.offset = offset +} + +// Retain increases the reference count by 1. +// Retain may be called simultaneously from multiple goroutines. +func (d *Data) Retain() { + atomic.AddInt64(&d.refCount, 1) +} + +// Release decreases the reference count by 1. +// When the reference count goes to zero, the memory is freed. +// Release may be called simultaneously from multiple goroutines. +func (d *Data) Release() { + debug.Assert(atomic.LoadInt64(&d.refCount) > 0, "too many releases") + + if atomic.AddInt64(&d.refCount, -1) == 0 { + for _, b := range d.buffers { + if b != nil { + b.Release() + } + } + + for _, b := range d.childData { + b.Release() + } + + if d.dictionary != nil { + d.dictionary.Release() + } + d.dictionary, d.buffers, d.childData = nil, nil, nil + } +} + +// DataType returns the DataType of the data. +func (d *Data) DataType() arrow.DataType { return d.dtype } + +func (d *Data) SetNullN(n int) { d.nulls = n } + +// NullN returns the number of nulls. +func (d *Data) NullN() int { return d.nulls } + +// Len returns the length. +func (d *Data) Len() int { return d.length } + +// Offset returns the offset. +func (d *Data) Offset() int { return d.offset } + +// Buffers returns the buffers. +func (d *Data) Buffers() []*memory.Buffer { return d.buffers } + +func (d *Data) Children() []arrow.ArrayData { return d.childData } + +// Dictionary returns the ArrayData object for the dictionary member, or nil +func (d *Data) Dictionary() arrow.ArrayData { return d.dictionary } + +// SetDictionary allows replacing the dictionary for this particular Data object +func (d *Data) SetDictionary(dict arrow.ArrayData) { + if d.dictionary != nil { + d.dictionary.Release() + d.dictionary = nil + } + if dict.(*Data) != nil { + dict.Retain() + d.dictionary = dict.(*Data) + } +} + +// NewSliceData returns a new slice that shares backing data with the input. +// The returned Data slice starts at i and extends j-i elements, such as: +// slice := data[i:j] +// The returned value must be Release'd after use. +// +// NewSliceData panics if the slice is outside the valid range of the input Data. +// NewSliceData panics if j < i. +func NewSliceData(data arrow.ArrayData, i, j int64) arrow.ArrayData { + if j > int64(data.Len()) || i > j || data.Offset()+int(i) > data.Offset()+data.Len() { + panic("arrow/array: index out of range") + } + + for _, b := range data.Buffers() { + if b != nil { + b.Retain() + } + } + + for _, child := range data.Children() { + if child != nil { + child.Retain() + } + } + + if data.(*Data).dictionary != nil { + data.(*Data).dictionary.Retain() + } + + o := &Data{ + refCount: 1, + dtype: data.DataType(), + nulls: UnknownNullCount, + length: int(j - i), + offset: data.Offset() + int(i), + buffers: data.Buffers(), + childData: data.Children(), + dictionary: data.(*Data).dictionary, + } + + if data.NullN() == 0 { + o.nulls = 0 + } + + return o +} + +func Hash(h *maphash.Hash, data arrow.ArrayData) { + a := data.(*Data) + + h.Write((*[bits.UintSize / 8]byte)(unsafe.Pointer(&a.length))[:]) + h.Write((*[bits.UintSize / 8]byte)(unsafe.Pointer(&a.length))[:]) + if len(a.buffers) > 0 && a.buffers[0] != nil { + h.Write(a.buffers[0].Bytes()) + } + for _, c := range a.childData { + Hash(h, c) + } +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array/decimal128.go b/vendor/github.com/apache/arrow/go/v14/arrow/array/decimal128.go new file mode 100644 index 000000000..331753168 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array/decimal128.go @@ -0,0 +1,365 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package array + +import ( + "bytes" + "fmt" + "math" + "math/big" + "reflect" + "strings" + "sync/atomic" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/bitutil" + "github.com/apache/arrow/go/v14/arrow/decimal128" + "github.com/apache/arrow/go/v14/arrow/internal/debug" + "github.com/apache/arrow/go/v14/arrow/memory" + "github.com/apache/arrow/go/v14/internal/json" +) + +// A type which represents an immutable sequence of 128-bit decimal values. +type Decimal128 struct { + array + + values []decimal128.Num +} + +func NewDecimal128Data(data arrow.ArrayData) *Decimal128 { + a := &Decimal128{} + a.refCount = 1 + a.setData(data.(*Data)) + return a +} + +func (a *Decimal128) Value(i int) decimal128.Num { return a.values[i] } + +func (a *Decimal128) ValueStr(i int) string { + if a.IsNull(i) { + return NullValueStr + } + return a.GetOneForMarshal(i).(string) +} + +func (a *Decimal128) Values() []decimal128.Num { return a.values } + +func (a *Decimal128) String() string { + o := new(strings.Builder) + o.WriteString("[") + for i := 0; i < a.Len(); i++ { + if i > 0 { + fmt.Fprintf(o, " ") + } + switch { + case a.IsNull(i): + o.WriteString(NullValueStr) + default: + fmt.Fprintf(o, "%v", a.Value(i)) + } + } + o.WriteString("]") + return o.String() +} + +func (a *Decimal128) setData(data *Data) { + a.array.setData(data) + vals := data.buffers[1] + if vals != nil { + a.values = arrow.Decimal128Traits.CastFromBytes(vals.Bytes()) + beg := a.array.data.offset + end := beg + a.array.data.length + a.values = a.values[beg:end] + } +} + +func (a *Decimal128) GetOneForMarshal(i int) interface{} { + if a.IsNull(i) { + return nil + } + + typ := a.DataType().(*arrow.Decimal128Type) + f := (&big.Float{}).SetInt(a.Value(i).BigInt()) + f.Quo(f, big.NewFloat(math.Pow10(int(typ.Scale)))) + return f.Text('g', int(typ.Precision)) +} + +// ["1.23", ] +func (a *Decimal128) MarshalJSON() ([]byte, error) { + vals := make([]interface{}, a.Len()) + for i := 0; i < a.Len(); i++ { + vals[i] = a.GetOneForMarshal(i) + } + return json.Marshal(vals) +} + +func arrayEqualDecimal128(left, right *Decimal128) bool { + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + if left.Value(i) != right.Value(i) { + return false + } + } + return true +} + +type Decimal128Builder struct { + builder + + dtype *arrow.Decimal128Type + data *memory.Buffer + rawData []decimal128.Num +} + +func NewDecimal128Builder(mem memory.Allocator, dtype *arrow.Decimal128Type) *Decimal128Builder { + return &Decimal128Builder{ + builder: builder{refCount: 1, mem: mem}, + dtype: dtype, + } +} + +func (b *Decimal128Builder) Type() arrow.DataType { return b.dtype } + +// Release decreases the reference count by 1. +// When the reference count goes to zero, the memory is freed. +func (b *Decimal128Builder) Release() { + debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases") + + if atomic.AddInt64(&b.refCount, -1) == 0 { + if b.nullBitmap != nil { + b.nullBitmap.Release() + b.nullBitmap = nil + } + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + } +} + +func (b *Decimal128Builder) Append(v decimal128.Num) { + b.Reserve(1) + b.UnsafeAppend(v) +} + +func (b *Decimal128Builder) UnsafeAppend(v decimal128.Num) { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + b.rawData[b.length] = v + b.length++ +} + +func (b *Decimal128Builder) AppendNull() { + b.Reserve(1) + b.UnsafeAppendBoolToBitmap(false) +} + +func (b *Decimal128Builder) AppendNulls(n int) { + for i := 0; i < n; i++ { + b.AppendNull() + } +} + +func (b *Decimal128Builder) AppendEmptyValue() { + b.Append(decimal128.Num{}) +} + +func (b *Decimal128Builder) AppendEmptyValues(n int) { + for i := 0; i < n; i++ { + b.AppendEmptyValue() + } +} + +func (b *Decimal128Builder) UnsafeAppendBoolToBitmap(isValid bool) { + if isValid { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + } else { + b.nulls++ + } + b.length++ +} + +// AppendValues will append the values in the v slice. The valid slice determines which values +// in v are valid (not null). The valid slice must either be empty or be equal in length to v. If empty, +// all values in v are appended and considered valid. +func (b *Decimal128Builder) AppendValues(v []decimal128.Num, valid []bool) { + if len(v) != len(valid) && len(valid) != 0 { + panic("len(v) != len(valid) && len(valid) != 0") + } + + if len(v) == 0 { + return + } + + b.Reserve(len(v)) + if len(v) > 0 { + arrow.Decimal128Traits.Copy(b.rawData[b.length:], v) + } + b.builder.unsafeAppendBoolsToBitmap(valid, len(v)) +} + +func (b *Decimal128Builder) init(capacity int) { + b.builder.init(capacity) + + b.data = memory.NewResizableBuffer(b.mem) + bytesN := arrow.Decimal128Traits.BytesRequired(capacity) + b.data.Resize(bytesN) + b.rawData = arrow.Decimal128Traits.CastFromBytes(b.data.Bytes()) +} + +// Reserve ensures there is enough space for appending n elements +// by checking the capacity and calling Resize if necessary. +func (b *Decimal128Builder) Reserve(n int) { + b.builder.reserve(n, b.Resize) +} + +// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(), +// additional memory will be allocated. If n is smaller, the allocated memory may reduced. +func (b *Decimal128Builder) Resize(n int) { + nBuilder := n + if n < minBuilderCapacity { + n = minBuilderCapacity + } + + if b.capacity == 0 { + b.init(n) + } else { + b.builder.resize(nBuilder, b.init) + b.data.Resize(arrow.Decimal128Traits.BytesRequired(n)) + b.rawData = arrow.Decimal128Traits.CastFromBytes(b.data.Bytes()) + } +} + +// NewArray creates a Decimal128 array from the memory buffers used by the builder and resets the Decimal128Builder +// so it can be used to build a new array. +func (b *Decimal128Builder) NewArray() arrow.Array { + return b.NewDecimal128Array() +} + +// NewDecimal128Array creates a Decimal128 array from the memory buffers used by the builder and resets the Decimal128Builder +// so it can be used to build a new array. +func (b *Decimal128Builder) NewDecimal128Array() (a *Decimal128) { + data := b.newData() + a = NewDecimal128Data(data) + data.Release() + return +} + +func (b *Decimal128Builder) newData() (data *Data) { + bytesRequired := arrow.Decimal128Traits.BytesRequired(b.length) + if bytesRequired > 0 && bytesRequired < b.data.Len() { + // trim buffers + b.data.Resize(bytesRequired) + } + data = NewData(b.dtype, b.length, []*memory.Buffer{b.nullBitmap, b.data}, nil, b.nulls, 0) + b.reset() + + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + + return +} + +func (b *Decimal128Builder) AppendValueFromString(s string) error { + if s == NullValueStr { + b.AppendNull() + return nil + } + val, err := decimal128.FromString(s, b.dtype.Precision, b.dtype.Scale) + if err != nil { + b.AppendNull() + return err + } + b.Append(val) + return nil +} + +func (b *Decimal128Builder) UnmarshalOne(dec *json.Decoder) error { + t, err := dec.Token() + if err != nil { + return err + } + + switch v := t.(type) { + case float64: + val, err := decimal128.FromFloat64(v, b.dtype.Precision, b.dtype.Scale) + if err != nil { + return err + } + b.Append(val) + case string: + val, err := decimal128.FromString(v, b.dtype.Precision, b.dtype.Scale) + if err != nil { + return err + } + b.Append(val) + case json.Number: + val, err := decimal128.FromString(v.String(), b.dtype.Precision, b.dtype.Scale) + if err != nil { + return err + } + b.Append(val) + case nil: + b.AppendNull() + return nil + default: + return &json.UnmarshalTypeError{ + Value: fmt.Sprint(t), + Type: reflect.TypeOf(decimal128.Num{}), + Offset: dec.InputOffset(), + } + } + + return nil +} + +func (b *Decimal128Builder) Unmarshal(dec *json.Decoder) error { + for dec.More() { + if err := b.UnmarshalOne(dec); err != nil { + return err + } + } + return nil +} + +// UnmarshalJSON will add the unmarshalled values to this builder. +// +// If the values are strings, they will get parsed with big.ParseFloat using +// a rounding mode of big.ToNearestAway currently. +func (b *Decimal128Builder) UnmarshalJSON(data []byte) error { + dec := json.NewDecoder(bytes.NewReader(data)) + t, err := dec.Token() + if err != nil { + return err + } + + if delim, ok := t.(json.Delim); !ok || delim != '[' { + return fmt.Errorf("decimal128 builder must unpack from json array, found %s", delim) + } + + return b.Unmarshal(dec) +} + +var ( + _ arrow.Array = (*Decimal128)(nil) + _ Builder = (*Decimal128Builder)(nil) +) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array/decimal256.go b/vendor/github.com/apache/arrow/go/v14/arrow/array/decimal256.go new file mode 100644 index 000000000..d63544f78 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array/decimal256.go @@ -0,0 +1,364 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package array + +import ( + "bytes" + "fmt" + "math" + "math/big" + "reflect" + "strings" + "sync/atomic" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/bitutil" + "github.com/apache/arrow/go/v14/arrow/decimal256" + "github.com/apache/arrow/go/v14/arrow/internal/debug" + "github.com/apache/arrow/go/v14/arrow/memory" + "github.com/apache/arrow/go/v14/internal/json" +) + +// Decimal256 is a type that represents an immutable sequence of 256-bit decimal values. +type Decimal256 struct { + array + + values []decimal256.Num +} + +func NewDecimal256Data(data arrow.ArrayData) *Decimal256 { + a := &Decimal256{} + a.refCount = 1 + a.setData(data.(*Data)) + return a +} + +func (a *Decimal256) Value(i int) decimal256.Num { return a.values[i] } + +func (a *Decimal256) ValueStr(i int) string { + if a.IsNull(i) { + return NullValueStr + } + return a.GetOneForMarshal(i).(string) +} + +func (a *Decimal256) Values() []decimal256.Num { return a.values } + +func (a *Decimal256) String() string { + o := new(strings.Builder) + o.WriteString("[") + for i := 0; i < a.Len(); i++ { + if i > 0 { + fmt.Fprintf(o, " ") + } + switch { + case a.IsNull(i): + o.WriteString(NullValueStr) + default: + fmt.Fprintf(o, "%v", a.Value(i)) + } + } + o.WriteString("]") + return o.String() +} + +func (a *Decimal256) setData(data *Data) { + a.array.setData(data) + vals := data.buffers[1] + if vals != nil { + a.values = arrow.Decimal256Traits.CastFromBytes(vals.Bytes()) + beg := a.array.data.offset + end := beg + a.array.data.length + a.values = a.values[beg:end] + } +} + +func (a *Decimal256) GetOneForMarshal(i int) interface{} { + if a.IsNull(i) { + return nil + } + + typ := a.DataType().(*arrow.Decimal256Type) + f := (&big.Float{}).SetInt(a.Value(i).BigInt()) + f.Quo(f, big.NewFloat(math.Pow10(int(typ.Scale)))) + return f.Text('g', int(typ.Precision)) +} + +func (a *Decimal256) MarshalJSON() ([]byte, error) { + vals := make([]interface{}, a.Len()) + for i := 0; i < a.Len(); i++ { + vals[i] = a.GetOneForMarshal(i) + } + return json.Marshal(vals) +} + +func arrayEqualDecimal256(left, right *Decimal256) bool { + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + if left.Value(i) != right.Value(i) { + return false + } + } + return true +} + +type Decimal256Builder struct { + builder + + dtype *arrow.Decimal256Type + data *memory.Buffer + rawData []decimal256.Num +} + +func NewDecimal256Builder(mem memory.Allocator, dtype *arrow.Decimal256Type) *Decimal256Builder { + return &Decimal256Builder{ + builder: builder{refCount: 1, mem: mem}, + dtype: dtype, + } +} + +// Release decreases the reference count by 1. +// When the reference count goes to zero, the memory is freed. +func (b *Decimal256Builder) Release() { + debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases") + + if atomic.AddInt64(&b.refCount, -1) == 0 { + if b.nullBitmap != nil { + b.nullBitmap.Release() + b.nullBitmap = nil + } + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + } +} + +func (b *Decimal256Builder) Append(v decimal256.Num) { + b.Reserve(1) + b.UnsafeAppend(v) +} + +func (b *Decimal256Builder) UnsafeAppend(v decimal256.Num) { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + b.rawData[b.length] = v + b.length++ +} + +func (b *Decimal256Builder) AppendNull() { + b.Reserve(1) + b.UnsafeAppendBoolToBitmap(false) +} + +func (b *Decimal256Builder) AppendNulls(n int) { + for i := 0; i < n; i++ { + b.AppendNull() + } +} + +func (b *Decimal256Builder) AppendEmptyValue() { + b.Append(decimal256.Num{}) +} + +func (b *Decimal256Builder) AppendEmptyValues(n int) { + for i := 0; i < n; i++ { + b.AppendEmptyValue() + } +} + +func (b *Decimal256Builder) Type() arrow.DataType { return b.dtype } + +func (b *Decimal256Builder) UnsafeAppendBoolToBitmap(isValid bool) { + if isValid { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + } else { + b.nulls++ + } + b.length++ +} + +// AppendValues will append the values in the v slice. The valid slice determines which values +// in v are valid (not null). The valid slice must either be empty or be equal in length to v. If empty, +// all values in v are appended and considered valid. +func (b *Decimal256Builder) AppendValues(v []decimal256.Num, valid []bool) { + if len(v) != len(valid) && len(valid) != 0 { + panic("arrow/array: len(v) != len(valid) && len(valid) != 0") + } + + if len(v) == 0 { + return + } + + b.Reserve(len(v)) + if len(v) > 0 { + arrow.Decimal256Traits.Copy(b.rawData[b.length:], v) + } + b.builder.unsafeAppendBoolsToBitmap(valid, len(v)) +} + +func (b *Decimal256Builder) init(capacity int) { + b.builder.init(capacity) + + b.data = memory.NewResizableBuffer(b.mem) + bytesN := arrow.Decimal256Traits.BytesRequired(capacity) + b.data.Resize(bytesN) + b.rawData = arrow.Decimal256Traits.CastFromBytes(b.data.Bytes()) +} + +// Reserve ensures there is enough space for appending n elements +// by checking the capacity and calling Resize if necessary. +func (b *Decimal256Builder) Reserve(n int) { + b.builder.reserve(n, b.Resize) +} + +// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(), +// additional memory will be allocated. If n is smaller, the allocated memory may reduced. +func (b *Decimal256Builder) Resize(n int) { + nBuilder := n + if n < minBuilderCapacity { + n = minBuilderCapacity + } + + if b.capacity == 0 { + b.init(n) + } else { + b.builder.resize(nBuilder, b.init) + b.data.Resize(arrow.Decimal256Traits.BytesRequired(n)) + b.rawData = arrow.Decimal256Traits.CastFromBytes(b.data.Bytes()) + } +} + +// NewArray creates a Decimal256 array from the memory buffers used by the builder and resets the Decimal256Builder +// so it can be used to build a new array. +func (b *Decimal256Builder) NewArray() arrow.Array { + return b.NewDecimal256Array() +} + +// NewDecimal256Array creates a Decimal256 array from the memory buffers used by the builder and resets the Decimal256Builder +// so it can be used to build a new array. +func (b *Decimal256Builder) NewDecimal256Array() (a *Decimal256) { + data := b.newData() + a = NewDecimal256Data(data) + data.Release() + return +} + +func (b *Decimal256Builder) newData() (data *Data) { + bytesRequired := arrow.Decimal256Traits.BytesRequired(b.length) + if bytesRequired > 0 && bytesRequired < b.data.Len() { + // trim buffers + b.data.Resize(bytesRequired) + } + data = NewData(b.dtype, b.length, []*memory.Buffer{b.nullBitmap, b.data}, nil, b.nulls, 0) + b.reset() + + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + + return +} + +func (b *Decimal256Builder) AppendValueFromString(s string) error { + if s == NullValueStr { + b.AppendNull() + return nil + } + val, err := decimal256.FromString(s, b.dtype.Precision, b.dtype.Scale) + if err != nil { + b.AppendNull() + return err + } + b.Append(val) + return nil +} + +func (b *Decimal256Builder) UnmarshalOne(dec *json.Decoder) error { + t, err := dec.Token() + if err != nil { + return err + } + + switch v := t.(type) { + case float64: + val, err := decimal256.FromFloat64(v, b.dtype.Precision, b.dtype.Scale) + if err != nil { + return err + } + b.Append(val) + case string: + out, err := decimal256.FromString(v, b.dtype.Precision, b.dtype.Scale) + if err != nil { + return err + } + b.Append(out) + case json.Number: + out, err := decimal256.FromString(v.String(), b.dtype.Precision, b.dtype.Scale) + if err != nil { + return err + } + b.Append(out) + case nil: + b.AppendNull() + return nil + default: + return &json.UnmarshalTypeError{ + Value: fmt.Sprint(t), + Type: reflect.TypeOf(decimal256.Num{}), + Offset: dec.InputOffset(), + } + } + + return nil +} + +func (b *Decimal256Builder) Unmarshal(dec *json.Decoder) error { + for dec.More() { + if err := b.UnmarshalOne(dec); err != nil { + return err + } + } + return nil +} + +// UnmarshalJSON will add the unmarshalled values to this builder. +// +// If the values are strings, they will get parsed with big.ParseFloat using +// a rounding mode of big.ToNearestAway currently. +func (b *Decimal256Builder) UnmarshalJSON(data []byte) error { + dec := json.NewDecoder(bytes.NewReader(data)) + t, err := dec.Token() + if err != nil { + return err + } + + if delim, ok := t.(json.Delim); !ok || delim != '[' { + return fmt.Errorf("arrow/array: decimal256 builder must unpack from json array, found %s", delim) + } + + return b.Unmarshal(dec) +} + +var ( + _ arrow.Array = (*Decimal256)(nil) + _ Builder = (*Decimal256Builder)(nil) +) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array/dictionary.go b/vendor/github.com/apache/arrow/go/v14/arrow/array/dictionary.go new file mode 100644 index 000000000..d0a1c4dc9 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array/dictionary.go @@ -0,0 +1,1953 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package array + +import ( + "bytes" + "errors" + "fmt" + "math" + "math/bits" + "sync/atomic" + "unsafe" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/bitutil" + "github.com/apache/arrow/go/v14/arrow/decimal128" + "github.com/apache/arrow/go/v14/arrow/decimal256" + "github.com/apache/arrow/go/v14/arrow/float16" + "github.com/apache/arrow/go/v14/arrow/internal/debug" + "github.com/apache/arrow/go/v14/arrow/memory" + "github.com/apache/arrow/go/v14/internal/hashing" + "github.com/apache/arrow/go/v14/internal/json" + "github.com/apache/arrow/go/v14/internal/utils" +) + +// Dictionary represents the type for dictionary-encoded data with a data +// dependent dictionary. +// +// A dictionary array contains an array of non-negative integers (the "dictionary" +// indices") along with a data type containing a "dictionary" corresponding to +// the distinct values represented in the data. +// +// For example, the array: +// +// ["foo", "bar", "foo", "bar", "foo", "bar"] +// +// with dictionary ["bar", "foo"], would have the representation of: +// +// indices: [1, 0, 1, 0, 1, 0] +// dictionary: ["bar", "foo"] +// +// The indices in principle may be any integer type. +type Dictionary struct { + array + + indices arrow.Array + dict arrow.Array +} + +// NewDictionaryArray constructs a dictionary array with the provided indices +// and dictionary using the given type. +func NewDictionaryArray(typ arrow.DataType, indices, dict arrow.Array) *Dictionary { + a := &Dictionary{} + a.array.refCount = 1 + dictdata := NewData(typ, indices.Len(), indices.Data().Buffers(), indices.Data().Children(), indices.NullN(), indices.Data().Offset()) + dictdata.dictionary = dict.Data().(*Data) + dict.Data().Retain() + + defer dictdata.Release() + a.setData(dictdata) + return a +} + +// checkIndexBounds returns an error if any value in the provided integer +// arraydata is >= the passed upperlimit or < 0. otherwise nil +func checkIndexBounds(indices *Data, upperlimit uint64) error { + if indices.length == 0 { + return nil + } + + var maxval uint64 + switch indices.dtype.ID() { + case arrow.UINT8: + maxval = math.MaxUint8 + case arrow.UINT16: + maxval = math.MaxUint16 + case arrow.UINT32: + maxval = math.MaxUint32 + case arrow.UINT64: + maxval = math.MaxUint64 + } + // for unsigned integers, if the values array is larger than the maximum + // index value (especially for UINT8/UINT16), then there's no need to + // boundscheck. for signed integers we still need to bounds check + // because a value could be < 0. + isSigned := maxval == 0 + if !isSigned && upperlimit > maxval { + return nil + } + + start := indices.offset + end := indices.offset + indices.length + + // TODO(ARROW-15950): lift BitSetRunReader from parquet to utils + // and use it here for performance improvement. + + switch indices.dtype.ID() { + case arrow.INT8: + data := arrow.Int8Traits.CastFromBytes(indices.buffers[1].Bytes()) + min, max := utils.GetMinMaxInt8(data[start:end]) + if min < 0 || max >= int8(upperlimit) { + return fmt.Errorf("contains out of bounds index: min: %d, max: %d", min, max) + } + case arrow.UINT8: + data := arrow.Uint8Traits.CastFromBytes(indices.buffers[1].Bytes()) + _, max := utils.GetMinMaxUint8(data[start:end]) + if max >= uint8(upperlimit) { + return fmt.Errorf("contains out of bounds index: max: %d", max) + } + case arrow.INT16: + data := arrow.Int16Traits.CastFromBytes(indices.buffers[1].Bytes()) + min, max := utils.GetMinMaxInt16(data[start:end]) + if min < 0 || max >= int16(upperlimit) { + return fmt.Errorf("contains out of bounds index: min: %d, max: %d", min, max) + } + case arrow.UINT16: + data := arrow.Uint16Traits.CastFromBytes(indices.buffers[1].Bytes()) + _, max := utils.GetMinMaxUint16(data[start:end]) + if max >= uint16(upperlimit) { + return fmt.Errorf("contains out of bounds index: max: %d", max) + } + case arrow.INT32: + data := arrow.Int32Traits.CastFromBytes(indices.buffers[1].Bytes()) + min, max := utils.GetMinMaxInt32(data[start:end]) + if min < 0 || max >= int32(upperlimit) { + return fmt.Errorf("contains out of bounds index: min: %d, max: %d", min, max) + } + case arrow.UINT32: + data := arrow.Uint32Traits.CastFromBytes(indices.buffers[1].Bytes()) + _, max := utils.GetMinMaxUint32(data[start:end]) + if max >= uint32(upperlimit) { + return fmt.Errorf("contains out of bounds index: max: %d", max) + } + case arrow.INT64: + data := arrow.Int64Traits.CastFromBytes(indices.buffers[1].Bytes()) + min, max := utils.GetMinMaxInt64(data[start:end]) + if min < 0 || max >= int64(upperlimit) { + return fmt.Errorf("contains out of bounds index: min: %d, max: %d", min, max) + } + case arrow.UINT64: + data := arrow.Uint64Traits.CastFromBytes(indices.buffers[1].Bytes()) + _, max := utils.GetMinMaxUint64(data[indices.offset : indices.offset+indices.length]) + if max >= upperlimit { + return fmt.Errorf("contains out of bounds value: max: %d", max) + } + default: + return fmt.Errorf("invalid type for bounds checking: %T", indices.dtype) + } + + return nil +} + +// NewValidatedDictionaryArray constructs a dictionary array from the provided indices +// and dictionary arrays, while also performing validation checks to ensure correctness +// such as bounds checking at are usually skipped for performance. +func NewValidatedDictionaryArray(typ *arrow.DictionaryType, indices, dict arrow.Array) (*Dictionary, error) { + if indices.DataType().ID() != typ.IndexType.ID() { + return nil, fmt.Errorf("dictionary type index (%T) does not match indices array type (%T)", typ.IndexType, indices.DataType()) + } + + if !arrow.TypeEqual(typ.ValueType, dict.DataType()) { + return nil, fmt.Errorf("dictionary value type (%T) does not match dict array type (%T)", typ.ValueType, dict.DataType()) + } + + if err := checkIndexBounds(indices.Data().(*Data), uint64(dict.Len())); err != nil { + return nil, err + } + + return NewDictionaryArray(typ, indices, dict), nil +} + +// NewDictionaryData creates a strongly typed Dictionary array from +// an ArrayData object with a datatype of arrow.Dictionary and a dictionary +func NewDictionaryData(data arrow.ArrayData) *Dictionary { + a := &Dictionary{} + a.refCount = 1 + a.setData(data.(*Data)) + return a +} + +func (d *Dictionary) Retain() { + atomic.AddInt64(&d.refCount, 1) +} + +func (d *Dictionary) Release() { + debug.Assert(atomic.LoadInt64(&d.refCount) > 0, "too many releases") + + if atomic.AddInt64(&d.refCount, -1) == 0 { + d.data.Release() + d.data, d.nullBitmapBytes = nil, nil + d.indices.Release() + d.indices = nil + if d.dict != nil { + d.dict.Release() + d.dict = nil + } + } +} + +func (d *Dictionary) setData(data *Data) { + d.array.setData(data) + + dictType := data.dtype.(*arrow.DictionaryType) + if data.dictionary == nil { + if data.length > 0 { + panic("arrow/array: no dictionary set in Data for Dictionary array") + } + } else { + debug.Assert(arrow.TypeEqual(dictType.ValueType, data.dictionary.DataType()), "mismatched dictionary value types") + } + + indexData := NewData(dictType.IndexType, data.length, data.buffers, data.childData, data.nulls, data.offset) + defer indexData.Release() + d.indices = MakeFromData(indexData) +} + +// Dictionary returns the values array that makes up the dictionary for this +// array. +func (d *Dictionary) Dictionary() arrow.Array { + if d.dict == nil { + d.dict = MakeFromData(d.data.dictionary) + } + return d.dict +} + +// Indices returns the underlying array of indices as it's own array +func (d *Dictionary) Indices() arrow.Array { + return d.indices +} + +// CanCompareIndices returns true if the dictionary arrays can be compared +// without having to unify the dictionaries themselves first. +// This means that the index types are equal too. +func (d *Dictionary) CanCompareIndices(other *Dictionary) bool { + if !arrow.TypeEqual(d.indices.DataType(), other.indices.DataType()) { + return false + } + + minlen := int64(min(d.data.dictionary.length, other.data.dictionary.length)) + return SliceEqual(d.Dictionary(), 0, minlen, other.Dictionary(), 0, minlen) +} + +func (d *Dictionary) ValueStr(i int) string { + if d.IsNull(i) { + return NullValueStr + } + return d.Dictionary().ValueStr(d.GetValueIndex(i)) +} + +func (d *Dictionary) String() string { + return fmt.Sprintf("{ dictionary: %v\n indices: %v }", d.Dictionary(), d.Indices()) +} + +// GetValueIndex returns the dictionary index for the value at index i of the array. +// The actual value can be retrieved by using d.Dictionary().(valuetype).Value(d.GetValueIndex(i)) +func (d *Dictionary) GetValueIndex(i int) int { + indiceData := d.data.buffers[1].Bytes() + // we know the value is non-negative per the spec, so + // we can use the unsigned value regardless. + switch d.indices.DataType().ID() { + case arrow.UINT8, arrow.INT8: + return int(uint8(indiceData[d.data.offset+i])) + case arrow.UINT16, arrow.INT16: + return int(arrow.Uint16Traits.CastFromBytes(indiceData)[d.data.offset+i]) + case arrow.UINT32, arrow.INT32: + idx := arrow.Uint32Traits.CastFromBytes(indiceData)[d.data.offset+i] + debug.Assert(bits.UintSize == 64 || idx <= math.MaxInt32, "arrow/dictionary: truncation of index value") + return int(idx) + case arrow.UINT64, arrow.INT64: + idx := arrow.Uint64Traits.CastFromBytes(indiceData)[d.data.offset+i] + debug.Assert((bits.UintSize == 32 && idx <= math.MaxInt32) || (bits.UintSize == 64 && idx <= math.MaxInt64), "arrow/dictionary: truncation of index value") + return int(idx) + } + debug.Assert(false, "unreachable dictionary index") + return -1 +} + +func (d *Dictionary) GetOneForMarshal(i int) interface{} { + if d.IsNull(i) { + return nil + } + vidx := d.GetValueIndex(i) + return d.Dictionary().GetOneForMarshal(vidx) +} + +func (d *Dictionary) MarshalJSON() ([]byte, error) { + vals := make([]interface{}, d.Len()) + for i := 0; i < d.Len(); i++ { + vals[i] = d.GetOneForMarshal(i) + } + return json.Marshal(vals) +} + +func arrayEqualDict(l, r *Dictionary) bool { + return Equal(l.Dictionary(), r.Dictionary()) && Equal(l.indices, r.indices) +} + +func arrayApproxEqualDict(l, r *Dictionary, opt equalOption) bool { + return arrayApproxEqual(l.Dictionary(), r.Dictionary(), opt) && arrayApproxEqual(l.indices, r.indices, opt) +} + +// helper for building the properly typed indices of the dictionary builder +type IndexBuilder struct { + Builder + Append func(int) +} + +func createIndexBuilder(mem memory.Allocator, dt arrow.FixedWidthDataType) (ret IndexBuilder, err error) { + ret = IndexBuilder{Builder: NewBuilder(mem, dt)} + switch dt.ID() { + case arrow.INT8: + ret.Append = func(idx int) { + ret.Builder.(*Int8Builder).Append(int8(idx)) + } + case arrow.UINT8: + ret.Append = func(idx int) { + ret.Builder.(*Uint8Builder).Append(uint8(idx)) + } + case arrow.INT16: + ret.Append = func(idx int) { + ret.Builder.(*Int16Builder).Append(int16(idx)) + } + case arrow.UINT16: + ret.Append = func(idx int) { + ret.Builder.(*Uint16Builder).Append(uint16(idx)) + } + case arrow.INT32: + ret.Append = func(idx int) { + ret.Builder.(*Int32Builder).Append(int32(idx)) + } + case arrow.UINT32: + ret.Append = func(idx int) { + ret.Builder.(*Uint32Builder).Append(uint32(idx)) + } + case arrow.INT64: + ret.Append = func(idx int) { + ret.Builder.(*Int64Builder).Append(int64(idx)) + } + case arrow.UINT64: + ret.Append = func(idx int) { + ret.Builder.(*Uint64Builder).Append(uint64(idx)) + } + default: + debug.Assert(false, "dictionary index type must be integral") + err = fmt.Errorf("dictionary index type must be integral, not %s", dt) + } + + return +} + +// helper function to construct an appropriately typed memo table based on +// the value type for the dictionary +func createMemoTable(mem memory.Allocator, dt arrow.DataType) (ret hashing.MemoTable, err error) { + switch dt.ID() { + case arrow.INT8: + ret = hashing.NewInt8MemoTable(0) + case arrow.UINT8: + ret = hashing.NewUint8MemoTable(0) + case arrow.INT16: + ret = hashing.NewInt16MemoTable(0) + case arrow.UINT16: + ret = hashing.NewUint16MemoTable(0) + case arrow.INT32: + ret = hashing.NewInt32MemoTable(0) + case arrow.UINT32: + ret = hashing.NewUint32MemoTable(0) + case arrow.INT64: + ret = hashing.NewInt64MemoTable(0) + case arrow.UINT64: + ret = hashing.NewUint64MemoTable(0) + case arrow.DURATION, arrow.TIMESTAMP, arrow.DATE64, arrow.TIME64: + ret = hashing.NewInt64MemoTable(0) + case arrow.TIME32, arrow.DATE32, arrow.INTERVAL_MONTHS: + ret = hashing.NewInt32MemoTable(0) + case arrow.FLOAT16: + ret = hashing.NewUint16MemoTable(0) + case arrow.FLOAT32: + ret = hashing.NewFloat32MemoTable(0) + case arrow.FLOAT64: + ret = hashing.NewFloat64MemoTable(0) + case arrow.BINARY, arrow.FIXED_SIZE_BINARY, arrow.DECIMAL128, arrow.DECIMAL256, arrow.INTERVAL_DAY_TIME, arrow.INTERVAL_MONTH_DAY_NANO: + ret = hashing.NewBinaryMemoTable(0, 0, NewBinaryBuilder(mem, arrow.BinaryTypes.Binary)) + case arrow.STRING: + ret = hashing.NewBinaryMemoTable(0, 0, NewBinaryBuilder(mem, arrow.BinaryTypes.String)) + case arrow.NULL: + default: + err = fmt.Errorf("unimplemented dictionary value type, %s", dt) + } + + return +} + +type DictionaryBuilder interface { + Builder + + NewDictionaryArray() *Dictionary + NewDelta() (indices, delta arrow.Array, err error) + AppendArray(arrow.Array) error + AppendIndices([]int, []bool) + ResetFull() +} + +type dictionaryBuilder struct { + builder + + dt *arrow.DictionaryType + deltaOffset int + memoTable hashing.MemoTable + idxBuilder IndexBuilder +} + +// NewDictionaryBuilderWithDict initializes a dictionary builder and inserts the values from `init` as the first +// values in the dictionary, but does not insert them as values into the array. +func NewDictionaryBuilderWithDict(mem memory.Allocator, dt *arrow.DictionaryType, init arrow.Array) DictionaryBuilder { + if init != nil && !arrow.TypeEqual(dt.ValueType, init.DataType()) { + panic(fmt.Errorf("arrow/array: cannot initialize dictionary type %T with array of type %T", dt.ValueType, init.DataType())) + } + + idxbldr, err := createIndexBuilder(mem, dt.IndexType.(arrow.FixedWidthDataType)) + if err != nil { + panic(fmt.Errorf("arrow/array: unsupported builder for index type of %T", dt)) + } + + memo, err := createMemoTable(mem, dt.ValueType) + if err != nil { + panic(fmt.Errorf("arrow/array: unsupported builder for value type of %T", dt)) + } + + bldr := dictionaryBuilder{ + builder: builder{refCount: 1, mem: mem}, + idxBuilder: idxbldr, + memoTable: memo, + dt: dt, + } + + switch dt.ValueType.ID() { + case arrow.NULL: + ret := &NullDictionaryBuilder{bldr} + debug.Assert(init == nil, "arrow/array: doesn't make sense to init a null dictionary") + return ret + case arrow.UINT8: + ret := &Uint8DictionaryBuilder{bldr} + if init != nil { + if err = ret.InsertDictValues(init.(*Uint8)); err != nil { + panic(err) + } + } + return ret + case arrow.INT8: + ret := &Int8DictionaryBuilder{bldr} + if init != nil { + if err = ret.InsertDictValues(init.(*Int8)); err != nil { + panic(err) + } + } + return ret + case arrow.UINT16: + ret := &Uint16DictionaryBuilder{bldr} + if init != nil { + if err = ret.InsertDictValues(init.(*Uint16)); err != nil { + panic(err) + } + } + return ret + case arrow.INT16: + ret := &Int16DictionaryBuilder{bldr} + if init != nil { + if err = ret.InsertDictValues(init.(*Int16)); err != nil { + panic(err) + } + } + return ret + case arrow.UINT32: + ret := &Uint32DictionaryBuilder{bldr} + if init != nil { + if err = ret.InsertDictValues(init.(*Uint32)); err != nil { + panic(err) + } + } + return ret + case arrow.INT32: + ret := &Int32DictionaryBuilder{bldr} + if init != nil { + if err = ret.InsertDictValues(init.(*Int32)); err != nil { + panic(err) + } + } + return ret + case arrow.UINT64: + ret := &Uint64DictionaryBuilder{bldr} + if init != nil { + if err = ret.InsertDictValues(init.(*Uint64)); err != nil { + panic(err) + } + } + return ret + case arrow.INT64: + ret := &Int64DictionaryBuilder{bldr} + if init != nil { + if err = ret.InsertDictValues(init.(*Int64)); err != nil { + panic(err) + } + } + return ret + case arrow.FLOAT16: + ret := &Float16DictionaryBuilder{bldr} + if init != nil { + if err = ret.InsertDictValues(init.(*Float16)); err != nil { + panic(err) + } + } + return ret + case arrow.FLOAT32: + ret := &Float32DictionaryBuilder{bldr} + if init != nil { + if err = ret.InsertDictValues(init.(*Float32)); err != nil { + panic(err) + } + } + return ret + case arrow.FLOAT64: + ret := &Float64DictionaryBuilder{bldr} + if init != nil { + if err = ret.InsertDictValues(init.(*Float64)); err != nil { + panic(err) + } + } + return ret + case arrow.STRING: + ret := &BinaryDictionaryBuilder{bldr} + if init != nil { + if err = ret.InsertStringDictValues(init.(*String)); err != nil { + panic(err) + } + } + return ret + case arrow.BINARY: + ret := &BinaryDictionaryBuilder{bldr} + if init != nil { + if err = ret.InsertDictValues(init.(*Binary)); err != nil { + panic(err) + } + } + return ret + case arrow.FIXED_SIZE_BINARY: + ret := &FixedSizeBinaryDictionaryBuilder{ + bldr, dt.ValueType.(*arrow.FixedSizeBinaryType).ByteWidth, + } + if init != nil { + if err = ret.InsertDictValues(init.(*FixedSizeBinary)); err != nil { + panic(err) + } + } + return ret + case arrow.DATE32: + ret := &Date32DictionaryBuilder{bldr} + if init != nil { + if err = ret.InsertDictValues(init.(*Date32)); err != nil { + panic(err) + } + } + return ret + case arrow.DATE64: + ret := &Date64DictionaryBuilder{bldr} + if init != nil { + if err = ret.InsertDictValues(init.(*Date64)); err != nil { + panic(err) + } + } + return ret + case arrow.TIMESTAMP: + ret := &TimestampDictionaryBuilder{bldr} + if init != nil { + if err = ret.InsertDictValues(init.(*Timestamp)); err != nil { + panic(err) + } + } + return ret + case arrow.TIME32: + ret := &Time32DictionaryBuilder{bldr} + if init != nil { + if err = ret.InsertDictValues(init.(*Time32)); err != nil { + panic(err) + } + } + return ret + case arrow.TIME64: + ret := &Time64DictionaryBuilder{bldr} + if init != nil { + if err = ret.InsertDictValues(init.(*Time64)); err != nil { + panic(err) + } + } + return ret + case arrow.INTERVAL_MONTHS: + ret := &MonthIntervalDictionaryBuilder{bldr} + if init != nil { + if err = ret.InsertDictValues(init.(*MonthInterval)); err != nil { + panic(err) + } + } + return ret + case arrow.INTERVAL_DAY_TIME: + ret := &DayTimeDictionaryBuilder{bldr} + if init != nil { + if err = ret.InsertDictValues(init.(*DayTimeInterval)); err != nil { + panic(err) + } + } + return ret + case arrow.DECIMAL128: + ret := &Decimal128DictionaryBuilder{bldr} + if init != nil { + if err = ret.InsertDictValues(init.(*Decimal128)); err != nil { + panic(err) + } + } + return ret + case arrow.DECIMAL256: + ret := &Decimal256DictionaryBuilder{bldr} + if init != nil { + if err = ret.InsertDictValues(init.(*Decimal256)); err != nil { + panic(err) + } + } + return ret + case arrow.LIST: + case arrow.STRUCT: + case arrow.SPARSE_UNION: + case arrow.DENSE_UNION: + case arrow.DICTIONARY: + case arrow.MAP: + case arrow.EXTENSION: + case arrow.FIXED_SIZE_LIST: + case arrow.DURATION: + ret := &DurationDictionaryBuilder{bldr} + if init != nil { + if err = ret.InsertDictValues(init.(*Duration)); err != nil { + panic(err) + } + } + return ret + case arrow.LARGE_STRING: + case arrow.LARGE_BINARY: + case arrow.LARGE_LIST: + case arrow.INTERVAL_MONTH_DAY_NANO: + ret := &MonthDayNanoDictionaryBuilder{bldr} + if init != nil { + if err = ret.InsertDictValues(init.(*MonthDayNanoInterval)); err != nil { + panic(err) + } + } + return ret + } + + panic("arrow/array: unimplemented dictionary key type") +} + +func NewDictionaryBuilder(mem memory.Allocator, dt *arrow.DictionaryType) DictionaryBuilder { + return NewDictionaryBuilderWithDict(mem, dt, nil) +} + +func (b *dictionaryBuilder) Type() arrow.DataType { return b.dt } + +func (b *dictionaryBuilder) Release() { + debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases") + + if atomic.AddInt64(&b.refCount, -1) == 0 { + b.idxBuilder.Release() + b.idxBuilder.Builder = nil + if binmemo, ok := b.memoTable.(*hashing.BinaryMemoTable); ok { + binmemo.Release() + } + b.memoTable = nil + } +} + +func (b *dictionaryBuilder) AppendNull() { + b.length += 1 + b.nulls += 1 + b.idxBuilder.AppendNull() +} + +func (b *dictionaryBuilder) AppendNulls(n int) { + for i := 0; i < n; i++ { + b.AppendNull() + } +} + +func (b *dictionaryBuilder) AppendEmptyValue() { + b.length += 1 + b.idxBuilder.AppendEmptyValue() +} + +func (b *dictionaryBuilder) AppendEmptyValues(n int) { + for i := 0; i < n; i++ { + b.AppendEmptyValue() + } +} + +func (b *dictionaryBuilder) Reserve(n int) { + b.idxBuilder.Reserve(n) +} + +func (b *dictionaryBuilder) Resize(n int) { + b.idxBuilder.Resize(n) + b.length = b.idxBuilder.Len() +} + +func (b *dictionaryBuilder) ResetFull() { + b.builder.reset() + b.idxBuilder.NewArray().Release() + b.memoTable.Reset() +} + +func (b *dictionaryBuilder) Cap() int { return b.idxBuilder.Cap() } + +func (b *dictionaryBuilder) IsNull(i int) bool { return b.idxBuilder.IsNull(i) } + +func (b *dictionaryBuilder) UnmarshalJSON(data []byte) error { + dec := json.NewDecoder(bytes.NewReader(data)) + t, err := dec.Token() + if err != nil { + return err + } + + if delim, ok := t.(json.Delim); !ok || delim != '[' { + return fmt.Errorf("dictionary builder must upack from json array, found %s", delim) + } + + return b.Unmarshal(dec) +} + +func (b *dictionaryBuilder) Unmarshal(dec *json.Decoder) error { + bldr := NewBuilder(b.mem, b.dt.ValueType) + defer bldr.Release() + + if err := bldr.Unmarshal(dec); err != nil { + return err + } + + arr := bldr.NewArray() + defer arr.Release() + return b.AppendArray(arr) +} + +func (b *dictionaryBuilder) AppendValueFromString(s string) error { + bldr := NewBuilder(b.mem, b.dt.ValueType) + defer bldr.Release() + + if err := bldr.AppendValueFromString(s); err != nil { + return err + } + + arr := bldr.NewArray() + defer arr.Release() + return b.AppendArray(arr) +} + +func (b *dictionaryBuilder) UnmarshalOne(dec *json.Decoder) error { + bldr := NewBuilder(b.mem, b.dt.ValueType) + defer bldr.Release() + + if err := bldr.UnmarshalOne(dec); err != nil { + return err + } + + arr := bldr.NewArray() + defer arr.Release() + return b.AppendArray(arr) +} + +func (b *dictionaryBuilder) NewArray() arrow.Array { + return b.NewDictionaryArray() +} + +func (b *dictionaryBuilder) newData() *Data { + indices, dict, err := b.newWithDictOffset(0) + if err != nil { + panic(err) + } + + indices.dtype = b.dt + indices.dictionary = dict + return indices +} + +func (b *dictionaryBuilder) NewDictionaryArray() *Dictionary { + a := &Dictionary{} + a.refCount = 1 + + indices := b.newData() + a.setData(indices) + indices.Release() + return a +} + +func (b *dictionaryBuilder) newWithDictOffset(offset int) (indices, dict *Data, err error) { + idxarr := b.idxBuilder.NewArray() + defer idxarr.Release() + + indices = idxarr.Data().(*Data) + + b.deltaOffset = b.memoTable.Size() + dict, err = GetDictArrayData(b.mem, b.dt.ValueType, b.memoTable, offset) + b.reset() + indices.Retain() + return +} + +// NewDelta returns the dictionary indices and a delta dictionary since the +// last time NewArray or NewDictionaryArray were called, and resets the state +// of the builder (except for the dictionary / memotable) +func (b *dictionaryBuilder) NewDelta() (indices, delta arrow.Array, err error) { + indicesData, deltaData, err := b.newWithDictOffset(b.deltaOffset) + if err != nil { + return nil, nil, err + } + + defer indicesData.Release() + defer deltaData.Release() + indices, delta = MakeFromData(indicesData), MakeFromData(deltaData) + return +} + +func (b *dictionaryBuilder) insertDictValue(val interface{}) error { + _, _, err := b.memoTable.GetOrInsert(val) + return err +} + +func (b *dictionaryBuilder) insertDictBytes(val []byte) error { + _, _, err := b.memoTable.GetOrInsertBytes(val) + return err +} + +func (b *dictionaryBuilder) appendValue(val interface{}) error { + idx, _, err := b.memoTable.GetOrInsert(val) + b.idxBuilder.Append(idx) + b.length += 1 + return err +} + +func (b *dictionaryBuilder) appendBytes(val []byte) error { + idx, _, err := b.memoTable.GetOrInsertBytes(val) + b.idxBuilder.Append(idx) + b.length += 1 + return err +} + +func getvalFn(arr arrow.Array) func(i int) interface{} { + switch typedarr := arr.(type) { + case *Int8: + return func(i int) interface{} { return typedarr.Value(i) } + case *Uint8: + return func(i int) interface{} { return typedarr.Value(i) } + case *Int16: + return func(i int) interface{} { return typedarr.Value(i) } + case *Uint16: + return func(i int) interface{} { return typedarr.Value(i) } + case *Int32: + return func(i int) interface{} { return typedarr.Value(i) } + case *Uint32: + return func(i int) interface{} { return typedarr.Value(i) } + case *Int64: + return func(i int) interface{} { return typedarr.Value(i) } + case *Uint64: + return func(i int) interface{} { return typedarr.Value(i) } + case *Float16: + return func(i int) interface{} { return typedarr.Value(i).Uint16() } + case *Float32: + return func(i int) interface{} { return typedarr.Value(i) } + case *Float64: + return func(i int) interface{} { return typedarr.Value(i) } + case *Duration: + return func(i int) interface{} { return int64(typedarr.Value(i)) } + case *Timestamp: + return func(i int) interface{} { return int64(typedarr.Value(i)) } + case *Date64: + return func(i int) interface{} { return int64(typedarr.Value(i)) } + case *Time64: + return func(i int) interface{} { return int64(typedarr.Value(i)) } + case *Time32: + return func(i int) interface{} { return int32(typedarr.Value(i)) } + case *Date32: + return func(i int) interface{} { return int32(typedarr.Value(i)) } + case *MonthInterval: + return func(i int) interface{} { return int32(typedarr.Value(i)) } + case *Binary: + return func(i int) interface{} { return typedarr.Value(i) } + case *FixedSizeBinary: + return func(i int) interface{} { return typedarr.Value(i) } + case *String: + return func(i int) interface{} { return typedarr.Value(i) } + case *Decimal128: + return func(i int) interface{} { + val := typedarr.Value(i) + return (*(*[arrow.Decimal128SizeBytes]byte)(unsafe.Pointer(&val)))[:] + } + case *Decimal256: + return func(i int) interface{} { + val := typedarr.Value(i) + return (*(*[arrow.Decimal256SizeBytes]byte)(unsafe.Pointer(&val)))[:] + } + case *DayTimeInterval: + return func(i int) interface{} { + val := typedarr.Value(i) + return (*(*[arrow.DayTimeIntervalSizeBytes]byte)(unsafe.Pointer(&val)))[:] + } + case *MonthDayNanoInterval: + return func(i int) interface{} { + val := typedarr.Value(i) + return (*(*[arrow.MonthDayNanoIntervalSizeBytes]byte)(unsafe.Pointer(&val)))[:] + } + } + + panic("arrow/array: invalid dictionary value type") +} + +func (b *dictionaryBuilder) AppendArray(arr arrow.Array) error { + debug.Assert(arrow.TypeEqual(b.dt.ValueType, arr.DataType()), "wrong value type of array to append to dict") + + valfn := getvalFn(arr) + for i := 0; i < arr.Len(); i++ { + if arr.IsNull(i) { + b.AppendNull() + } else { + if err := b.appendValue(valfn(i)); err != nil { + return err + } + } + } + return nil +} + +func (b *dictionaryBuilder) IndexBuilder() IndexBuilder { + return b.idxBuilder +} + +func (b *dictionaryBuilder) AppendIndices(indices []int, valid []bool) { + b.length += len(indices) + switch idxbldr := b.idxBuilder.Builder.(type) { + case *Int8Builder: + vals := make([]int8, len(indices)) + for i, v := range indices { + vals[i] = int8(v) + } + idxbldr.AppendValues(vals, valid) + case *Int16Builder: + vals := make([]int16, len(indices)) + for i, v := range indices { + vals[i] = int16(v) + } + idxbldr.AppendValues(vals, valid) + case *Int32Builder: + vals := make([]int32, len(indices)) + for i, v := range indices { + vals[i] = int32(v) + } + idxbldr.AppendValues(vals, valid) + case *Int64Builder: + vals := make([]int64, len(indices)) + for i, v := range indices { + vals[i] = int64(v) + } + idxbldr.AppendValues(vals, valid) + case *Uint8Builder: + vals := make([]uint8, len(indices)) + for i, v := range indices { + vals[i] = uint8(v) + } + idxbldr.AppendValues(vals, valid) + case *Uint16Builder: + vals := make([]uint16, len(indices)) + for i, v := range indices { + vals[i] = uint16(v) + } + idxbldr.AppendValues(vals, valid) + case *Uint32Builder: + vals := make([]uint32, len(indices)) + for i, v := range indices { + vals[i] = uint32(v) + } + idxbldr.AppendValues(vals, valid) + case *Uint64Builder: + vals := make([]uint64, len(indices)) + for i, v := range indices { + vals[i] = uint64(v) + } + idxbldr.AppendValues(vals, valid) + } +} + +type NullDictionaryBuilder struct { + dictionaryBuilder +} + +func (b *NullDictionaryBuilder) NewArray() arrow.Array { + return b.NewDictionaryArray() +} + +func (b *NullDictionaryBuilder) NewDictionaryArray() *Dictionary { + idxarr := b.idxBuilder.NewArray() + defer idxarr.Release() + + out := idxarr.Data().(*Data) + dictarr := NewNull(0) + defer dictarr.Release() + + dictarr.data.Retain() + out.dtype = b.dt + out.dictionary = dictarr.data + + return NewDictionaryData(out) +} + +func (b *NullDictionaryBuilder) AppendArray(arr arrow.Array) error { + if arr.DataType().ID() != arrow.NULL { + return fmt.Errorf("cannot append non-null array to null dictionary") + } + + for i := 0; i < arr.(*Null).Len(); i++ { + b.AppendNull() + } + return nil +} + +type Int8DictionaryBuilder struct { + dictionaryBuilder +} + +func (b *Int8DictionaryBuilder) Append(v int8) error { return b.appendValue(v) } +func (b *Int8DictionaryBuilder) InsertDictValues(arr *Int8) (err error) { + for _, v := range arr.values { + if err = b.insertDictValue(v); err != nil { + break + } + } + return +} + +type Uint8DictionaryBuilder struct { + dictionaryBuilder +} + +func (b *Uint8DictionaryBuilder) Append(v uint8) error { return b.appendValue(v) } +func (b *Uint8DictionaryBuilder) InsertDictValues(arr *Uint8) (err error) { + for _, v := range arr.values { + if err = b.insertDictValue(v); err != nil { + break + } + } + return +} + +type Int16DictionaryBuilder struct { + dictionaryBuilder +} + +func (b *Int16DictionaryBuilder) Append(v int16) error { return b.appendValue(v) } +func (b *Int16DictionaryBuilder) InsertDictValues(arr *Int16) (err error) { + for _, v := range arr.values { + if err = b.insertDictValue(v); err != nil { + break + } + } + return +} + +type Uint16DictionaryBuilder struct { + dictionaryBuilder +} + +func (b *Uint16DictionaryBuilder) Append(v uint16) error { return b.appendValue(v) } +func (b *Uint16DictionaryBuilder) InsertDictValues(arr *Uint16) (err error) { + for _, v := range arr.values { + if err = b.insertDictValue(v); err != nil { + break + } + } + return +} + +type Int32DictionaryBuilder struct { + dictionaryBuilder +} + +func (b *Int32DictionaryBuilder) Append(v int32) error { return b.appendValue(v) } +func (b *Int32DictionaryBuilder) InsertDictValues(arr *Int32) (err error) { + for _, v := range arr.values { + if err = b.insertDictValue(v); err != nil { + break + } + } + return +} + +type Uint32DictionaryBuilder struct { + dictionaryBuilder +} + +func (b *Uint32DictionaryBuilder) Append(v uint32) error { return b.appendValue(v) } +func (b *Uint32DictionaryBuilder) InsertDictValues(arr *Uint32) (err error) { + for _, v := range arr.values { + if err = b.insertDictValue(v); err != nil { + break + } + } + return +} + +type Int64DictionaryBuilder struct { + dictionaryBuilder +} + +func (b *Int64DictionaryBuilder) Append(v int64) error { return b.appendValue(v) } +func (b *Int64DictionaryBuilder) InsertDictValues(arr *Int64) (err error) { + for _, v := range arr.values { + if err = b.insertDictValue(v); err != nil { + break + } + } + return +} + +type Uint64DictionaryBuilder struct { + dictionaryBuilder +} + +func (b *Uint64DictionaryBuilder) Append(v uint64) error { return b.appendValue(v) } +func (b *Uint64DictionaryBuilder) InsertDictValues(arr *Uint64) (err error) { + for _, v := range arr.values { + if err = b.insertDictValue(v); err != nil { + break + } + } + return +} + +type DurationDictionaryBuilder struct { + dictionaryBuilder +} + +func (b *DurationDictionaryBuilder) Append(v arrow.Duration) error { return b.appendValue(int64(v)) } +func (b *DurationDictionaryBuilder) InsertDictValues(arr *Duration) (err error) { + for _, v := range arr.values { + if err = b.insertDictValue(int64(v)); err != nil { + break + } + } + return +} + +type TimestampDictionaryBuilder struct { + dictionaryBuilder +} + +func (b *TimestampDictionaryBuilder) Append(v arrow.Timestamp) error { return b.appendValue(int64(v)) } +func (b *TimestampDictionaryBuilder) InsertDictValues(arr *Timestamp) (err error) { + for _, v := range arr.values { + if err = b.insertDictValue(int64(v)); err != nil { + break + } + } + return +} + +type Time32DictionaryBuilder struct { + dictionaryBuilder +} + +func (b *Time32DictionaryBuilder) Append(v arrow.Time32) error { return b.appendValue(int32(v)) } +func (b *Time32DictionaryBuilder) InsertDictValues(arr *Time32) (err error) { + for _, v := range arr.values { + if err = b.insertDictValue(int32(v)); err != nil { + break + } + } + return +} + +type Time64DictionaryBuilder struct { + dictionaryBuilder +} + +func (b *Time64DictionaryBuilder) Append(v arrow.Time64) error { return b.appendValue(int64(v)) } +func (b *Time64DictionaryBuilder) InsertDictValues(arr *Time64) (err error) { + for _, v := range arr.values { + if err = b.insertDictValue(int64(v)); err != nil { + break + } + } + return +} + +type Date32DictionaryBuilder struct { + dictionaryBuilder +} + +func (b *Date32DictionaryBuilder) Append(v arrow.Date32) error { return b.appendValue(int32(v)) } +func (b *Date32DictionaryBuilder) InsertDictValues(arr *Date32) (err error) { + for _, v := range arr.values { + if err = b.insertDictValue(int32(v)); err != nil { + break + } + } + return +} + +type Date64DictionaryBuilder struct { + dictionaryBuilder +} + +func (b *Date64DictionaryBuilder) Append(v arrow.Date64) error { return b.appendValue(int64(v)) } +func (b *Date64DictionaryBuilder) InsertDictValues(arr *Date64) (err error) { + for _, v := range arr.values { + if err = b.insertDictValue(int64(v)); err != nil { + break + } + } + return +} + +type MonthIntervalDictionaryBuilder struct { + dictionaryBuilder +} + +func (b *MonthIntervalDictionaryBuilder) Append(v arrow.MonthInterval) error { + return b.appendValue(int32(v)) +} +func (b *MonthIntervalDictionaryBuilder) InsertDictValues(arr *MonthInterval) (err error) { + for _, v := range arr.values { + if err = b.insertDictValue(int32(v)); err != nil { + break + } + } + return +} + +type Float16DictionaryBuilder struct { + dictionaryBuilder +} + +func (b *Float16DictionaryBuilder) Append(v float16.Num) error { return b.appendValue(v.Uint16()) } +func (b *Float16DictionaryBuilder) InsertDictValues(arr *Float16) (err error) { + for _, v := range arr.values { + if err = b.insertDictValue(v.Uint16()); err != nil { + break + } + } + return +} + +type Float32DictionaryBuilder struct { + dictionaryBuilder +} + +func (b *Float32DictionaryBuilder) Append(v float32) error { return b.appendValue(v) } +func (b *Float32DictionaryBuilder) InsertDictValues(arr *Float32) (err error) { + for _, v := range arr.values { + if err = b.insertDictValue(v); err != nil { + break + } + } + return +} + +type Float64DictionaryBuilder struct { + dictionaryBuilder +} + +func (b *Float64DictionaryBuilder) Append(v float64) error { return b.appendValue(v) } +func (b *Float64DictionaryBuilder) InsertDictValues(arr *Float64) (err error) { + for _, v := range arr.values { + if err = b.insertDictValue(v); err != nil { + break + } + } + return +} + +type BinaryDictionaryBuilder struct { + dictionaryBuilder +} + +func (b *BinaryDictionaryBuilder) Append(v []byte) error { + if v == nil { + b.AppendNull() + return nil + } + + return b.appendBytes(v) +} + +func (b *BinaryDictionaryBuilder) AppendString(v string) error { return b.appendBytes([]byte(v)) } +func (b *BinaryDictionaryBuilder) InsertDictValues(arr *Binary) (err error) { + if !arrow.TypeEqual(arr.DataType(), b.dt.ValueType) { + return fmt.Errorf("dictionary insert type mismatch: cannot insert values of type %T to dictionary type %T", arr.DataType(), b.dt.ValueType) + } + + for i := 0; i < arr.Len(); i++ { + if err = b.insertDictBytes(arr.Value(i)); err != nil { + break + } + } + return +} +func (b *BinaryDictionaryBuilder) InsertStringDictValues(arr *String) (err error) { + if !arrow.TypeEqual(arr.DataType(), b.dt.ValueType) { + return fmt.Errorf("dictionary insert type mismatch: cannot insert values of type %T to dictionary type %T", arr.DataType(), b.dt.ValueType) + } + + for i := 0; i < arr.Len(); i++ { + if err = b.insertDictValue(arr.Value(i)); err != nil { + break + } + } + return +} + +func (b *BinaryDictionaryBuilder) GetValueIndex(i int) int { + switch b := b.idxBuilder.Builder.(type) { + case *Uint8Builder: + return int(b.Value(i)) + case *Int8Builder: + return int(b.Value(i)) + case *Uint16Builder: + return int(b.Value(i)) + case *Int16Builder: + return int(b.Value(i)) + case *Uint32Builder: + return int(b.Value(i)) + case *Int32Builder: + return int(b.Value(i)) + case *Uint64Builder: + return int(b.Value(i)) + case *Int64Builder: + return int(b.Value(i)) + default: + return -1 + } +} + +func (b *BinaryDictionaryBuilder) Value(i int) []byte { + switch mt := b.memoTable.(type) { + case *hashing.BinaryMemoTable: + return mt.Value(i) + } + return nil +} + +func (b *BinaryDictionaryBuilder) ValueStr(i int) string { + return string(b.Value(i)) +} + +type FixedSizeBinaryDictionaryBuilder struct { + dictionaryBuilder + byteWidth int +} + +func (b *FixedSizeBinaryDictionaryBuilder) Append(v []byte) error { + return b.appendValue(v[:b.byteWidth]) +} +func (b *FixedSizeBinaryDictionaryBuilder) InsertDictValues(arr *FixedSizeBinary) (err error) { + var ( + beg = arr.array.data.offset * b.byteWidth + end = (arr.array.data.offset + arr.data.length) * b.byteWidth + ) + data := arr.valueBytes[beg:end] + for len(data) > 0 { + if err = b.insertDictValue(data[:b.byteWidth]); err != nil { + break + } + data = data[b.byteWidth:] + } + return +} + +type Decimal128DictionaryBuilder struct { + dictionaryBuilder +} + +func (b *Decimal128DictionaryBuilder) Append(v decimal128.Num) error { + return b.appendValue((*(*[arrow.Decimal128SizeBytes]byte)(unsafe.Pointer(&v)))[:]) +} +func (b *Decimal128DictionaryBuilder) InsertDictValues(arr *Decimal128) (err error) { + data := arrow.Decimal128Traits.CastToBytes(arr.values) + for len(data) > 0 { + if err = b.insertDictValue(data[:arrow.Decimal128SizeBytes]); err != nil { + break + } + data = data[arrow.Decimal128SizeBytes:] + } + return +} + +type Decimal256DictionaryBuilder struct { + dictionaryBuilder +} + +func (b *Decimal256DictionaryBuilder) Append(v decimal256.Num) error { + return b.appendValue((*(*[arrow.Decimal256SizeBytes]byte)(unsafe.Pointer(&v)))[:]) +} +func (b *Decimal256DictionaryBuilder) InsertDictValues(arr *Decimal256) (err error) { + data := arrow.Decimal256Traits.CastToBytes(arr.values) + for len(data) > 0 { + if err = b.insertDictValue(data[:arrow.Decimal256SizeBytes]); err != nil { + break + } + data = data[arrow.Decimal256SizeBytes:] + } + return +} + +type MonthDayNanoDictionaryBuilder struct { + dictionaryBuilder +} + +func (b *MonthDayNanoDictionaryBuilder) Append(v arrow.MonthDayNanoInterval) error { + return b.appendValue((*(*[arrow.MonthDayNanoIntervalSizeBytes]byte)(unsafe.Pointer(&v)))[:]) +} +func (b *MonthDayNanoDictionaryBuilder) InsertDictValues(arr *MonthDayNanoInterval) (err error) { + data := arrow.MonthDayNanoIntervalTraits.CastToBytes(arr.values) + for len(data) > 0 { + if err = b.insertDictValue(data[:arrow.MonthDayNanoIntervalSizeBytes]); err != nil { + break + } + data = data[arrow.MonthDayNanoIntervalSizeBytes:] + } + return +} + +type DayTimeDictionaryBuilder struct { + dictionaryBuilder +} + +func (b *DayTimeDictionaryBuilder) Append(v arrow.DayTimeInterval) error { + return b.appendValue((*(*[arrow.DayTimeIntervalSizeBytes]byte)(unsafe.Pointer(&v)))[:]) +} +func (b *DayTimeDictionaryBuilder) InsertDictValues(arr *DayTimeInterval) (err error) { + data := arrow.DayTimeIntervalTraits.CastToBytes(arr.values) + for len(data) > 0 { + if err = b.insertDictValue(data[:arrow.DayTimeIntervalSizeBytes]); err != nil { + break + } + data = data[arrow.DayTimeIntervalSizeBytes:] + } + return +} + +func IsTrivialTransposition(transposeMap []int32) bool { + for i, t := range transposeMap { + if t != int32(i) { + return false + } + } + return true +} + +func TransposeDictIndices(mem memory.Allocator, data arrow.ArrayData, inType, outType arrow.DataType, dict arrow.ArrayData, transposeMap []int32) (arrow.ArrayData, error) { + // inType may be different from data->dtype if data is ExtensionType + if inType.ID() != arrow.DICTIONARY || outType.ID() != arrow.DICTIONARY { + return nil, errors.New("arrow/array: expected dictionary type") + } + + var ( + inDictType = inType.(*arrow.DictionaryType) + outDictType = outType.(*arrow.DictionaryType) + inIndexType = inDictType.IndexType + outIndexType = outDictType.IndexType.(arrow.FixedWidthDataType) + ) + + if inIndexType.ID() == outIndexType.ID() && IsTrivialTransposition(transposeMap) { + // index type and values will be identical, we can reuse the existing buffers + return NewDataWithDictionary(outType, data.Len(), []*memory.Buffer{data.Buffers()[0], data.Buffers()[1]}, + data.NullN(), data.Offset(), dict.(*Data)), nil + } + + // default path: compute the transposed indices as a new buffer + outBuf := memory.NewResizableBuffer(mem) + outBuf.Resize(data.Len() * int(bitutil.BytesForBits(int64(outIndexType.BitWidth())))) + defer outBuf.Release() + + // shift null buffer if original offset is non-zero + var nullBitmap *memory.Buffer + if data.Offset() != 0 && data.NullN() != 0 { + nullBitmap = memory.NewResizableBuffer(mem) + nullBitmap.Resize(int(bitutil.BytesForBits(int64(data.Len())))) + bitutil.CopyBitmap(data.Buffers()[0].Bytes(), data.Offset(), data.Len(), nullBitmap.Bytes(), 0) + defer nullBitmap.Release() + } else { + nullBitmap = data.Buffers()[0] + } + + outData := NewDataWithDictionary(outType, data.Len(), + []*memory.Buffer{nullBitmap, outBuf}, data.NullN(), 0, dict.(*Data)) + err := utils.TransposeIntsBuffers(inIndexType, outIndexType, + data.Buffers()[1].Bytes(), outBuf.Bytes(), data.Offset(), outData.offset, data.Len(), transposeMap) + return outData, err +} + +// DictionaryUnifier defines the interface used for unifying, and optionally producing +// transposition maps for, multiple dictionary arrays incrementally. +type DictionaryUnifier interface { + // Unify adds the provided array of dictionary values to be unified. + Unify(arrow.Array) error + // UnifyAndTranspose adds the provided array of dictionary values, + // just like Unify but returns an allocated buffer containing a mapping + // to transpose dictionary indices. + UnifyAndTranspose(dict arrow.Array) (transposed *memory.Buffer, err error) + // GetResult returns the dictionary type (choosing the smallest index type + // that can represent all the values) and the new unified dictionary. + // + // Calling GetResult clears the existing dictionary from the unifier so it + // can be reused by calling Unify/UnifyAndTranspose again with new arrays. + GetResult() (outType arrow.DataType, outDict arrow.Array, err error) + // GetResultWithIndexType is like GetResult, but allows specifying the type + // of the dictionary indexes rather than letting the unifier pick. If the + // passed in index type isn't large enough to represent all of the dictionary + // values, an error will be returned instead. The new unified dictionary + // is returned. + GetResultWithIndexType(indexType arrow.DataType) (arrow.Array, error) + // Release should be called to clean up any allocated scrach memo-table used + // for building the unified dictionary. + Release() +} + +type unifier struct { + mem memory.Allocator + valueType arrow.DataType + memoTable hashing.MemoTable +} + +// NewDictionaryUnifier constructs and returns a new dictionary unifier for dictionaries +// of valueType, using the provided allocator for allocating the unified dictionary +// and the memotable used for building it. +// +// This will only work for non-nested types currently. a nested valueType or dictionary type +// will result in an error. +func NewDictionaryUnifier(alloc memory.Allocator, valueType arrow.DataType) (DictionaryUnifier, error) { + memoTable, err := createMemoTable(alloc, valueType) + if err != nil { + return nil, err + } + return &unifier{ + mem: alloc, + valueType: valueType, + memoTable: memoTable, + }, nil +} + +func (u *unifier) Release() { + if bin, ok := u.memoTable.(*hashing.BinaryMemoTable); ok { + bin.Release() + } +} + +func (u *unifier) Unify(dict arrow.Array) (err error) { + if !arrow.TypeEqual(u.valueType, dict.DataType()) { + return fmt.Errorf("dictionary type different from unifier: %s, expected: %s", dict.DataType(), u.valueType) + } + + valFn := getvalFn(dict) + for i := 0; i < dict.Len(); i++ { + if dict.IsNull(i) { + u.memoTable.GetOrInsertNull() + continue + } + + if _, _, err = u.memoTable.GetOrInsert(valFn(i)); err != nil { + return err + } + } + return +} + +func (u *unifier) UnifyAndTranspose(dict arrow.Array) (transposed *memory.Buffer, err error) { + if !arrow.TypeEqual(u.valueType, dict.DataType()) { + return nil, fmt.Errorf("dictionary type different from unifier: %s, expected: %s", dict.DataType(), u.valueType) + } + + transposed = memory.NewResizableBuffer(u.mem) + transposed.Resize(arrow.Int32Traits.BytesRequired(dict.Len())) + + newIdxes := arrow.Int32Traits.CastFromBytes(transposed.Bytes()) + valFn := getvalFn(dict) + for i := 0; i < dict.Len(); i++ { + if dict.IsNull(i) { + idx, _ := u.memoTable.GetOrInsertNull() + newIdxes[i] = int32(idx) + continue + } + + idx, _, err := u.memoTable.GetOrInsert(valFn(i)) + if err != nil { + transposed.Release() + return nil, err + } + newIdxes[i] = int32(idx) + } + return +} + +func (u *unifier) GetResult() (outType arrow.DataType, outDict arrow.Array, err error) { + dictLen := u.memoTable.Size() + var indexType arrow.DataType + switch { + case dictLen <= math.MaxInt8: + indexType = arrow.PrimitiveTypes.Int8 + case dictLen <= math.MaxInt16: + indexType = arrow.PrimitiveTypes.Int16 + case dictLen <= math.MaxInt32: + indexType = arrow.PrimitiveTypes.Int32 + default: + indexType = arrow.PrimitiveTypes.Int64 + } + outType = &arrow.DictionaryType{IndexType: indexType, ValueType: u.valueType} + + dictData, err := GetDictArrayData(u.mem, u.valueType, u.memoTable, 0) + if err != nil { + return nil, nil, err + } + + u.memoTable.Reset() + + defer dictData.Release() + outDict = MakeFromData(dictData) + return +} + +func (u *unifier) GetResultWithIndexType(indexType arrow.DataType) (arrow.Array, error) { + dictLen := u.memoTable.Size() + var toobig bool + switch indexType.ID() { + case arrow.UINT8: + toobig = dictLen > math.MaxUint8 + case arrow.INT8: + toobig = dictLen > math.MaxInt8 + case arrow.UINT16: + toobig = dictLen > math.MaxUint16 + case arrow.INT16: + toobig = dictLen > math.MaxInt16 + case arrow.UINT32: + toobig = uint(dictLen) > math.MaxUint32 + case arrow.INT32: + toobig = dictLen > math.MaxInt32 + case arrow.UINT64: + toobig = uint64(dictLen) > uint64(math.MaxUint64) + case arrow.INT64: + default: + return nil, fmt.Errorf("arrow/array: invalid dictionary index type: %s, must be integral", indexType) + } + if toobig { + return nil, errors.New("arrow/array: cannot combine dictionaries. unified dictionary requires a larger index type") + } + + dictData, err := GetDictArrayData(u.mem, u.valueType, u.memoTable, 0) + if err != nil { + return nil, err + } + + u.memoTable.Reset() + + defer dictData.Release() + return MakeFromData(dictData), nil +} + +type binaryUnifier struct { + mem memory.Allocator + memoTable *hashing.BinaryMemoTable +} + +// NewBinaryDictionaryUnifier constructs and returns a new dictionary unifier for dictionaries +// of binary values, using the provided allocator for allocating the unified dictionary +// and the memotable used for building it. +func NewBinaryDictionaryUnifier(alloc memory.Allocator) DictionaryUnifier { + return &binaryUnifier{ + mem: alloc, + memoTable: hashing.NewBinaryMemoTable(0, 0, NewBinaryBuilder(alloc, arrow.BinaryTypes.Binary)), + } +} + +func (u *binaryUnifier) Release() { + u.memoTable.Release() +} + +func (u *binaryUnifier) Unify(dict arrow.Array) (err error) { + if !arrow.TypeEqual(arrow.BinaryTypes.Binary, dict.DataType()) { + return fmt.Errorf("dictionary type different from unifier: %s, expected: %s", dict.DataType(), arrow.BinaryTypes.Binary) + } + + typedDict := dict.(*Binary) + for i := 0; i < dict.Len(); i++ { + if dict.IsNull(i) { + u.memoTable.GetOrInsertNull() + continue + } + + if _, _, err = u.memoTable.GetOrInsertBytes(typedDict.Value(i)); err != nil { + return err + } + } + return +} + +func (u *binaryUnifier) UnifyAndTranspose(dict arrow.Array) (transposed *memory.Buffer, err error) { + if !arrow.TypeEqual(arrow.BinaryTypes.Binary, dict.DataType()) { + return nil, fmt.Errorf("dictionary type different from unifier: %s, expected: %s", dict.DataType(), arrow.BinaryTypes.Binary) + } + + transposed = memory.NewResizableBuffer(u.mem) + transposed.Resize(arrow.Int32Traits.BytesRequired(dict.Len())) + + newIdxes := arrow.Int32Traits.CastFromBytes(transposed.Bytes()) + typedDict := dict.(*Binary) + for i := 0; i < dict.Len(); i++ { + if dict.IsNull(i) { + idx, _ := u.memoTable.GetOrInsertNull() + newIdxes[i] = int32(idx) + continue + } + + idx, _, err := u.memoTable.GetOrInsertBytes(typedDict.Value(i)) + if err != nil { + transposed.Release() + return nil, err + } + newIdxes[i] = int32(idx) + } + return +} + +func (u *binaryUnifier) GetResult() (outType arrow.DataType, outDict arrow.Array, err error) { + dictLen := u.memoTable.Size() + var indexType arrow.DataType + switch { + case dictLen <= math.MaxInt8: + indexType = arrow.PrimitiveTypes.Int8 + case dictLen <= math.MaxInt16: + indexType = arrow.PrimitiveTypes.Int16 + case dictLen <= math.MaxInt32: + indexType = arrow.PrimitiveTypes.Int32 + default: + indexType = arrow.PrimitiveTypes.Int64 + } + outType = &arrow.DictionaryType{IndexType: indexType, ValueType: arrow.BinaryTypes.Binary} + + dictData, err := GetDictArrayData(u.mem, arrow.BinaryTypes.Binary, u.memoTable, 0) + if err != nil { + return nil, nil, err + } + + u.memoTable.Reset() + + defer dictData.Release() + outDict = MakeFromData(dictData) + return +} + +func (u *binaryUnifier) GetResultWithIndexType(indexType arrow.DataType) (arrow.Array, error) { + dictLen := u.memoTable.Size() + var toobig bool + switch indexType.ID() { + case arrow.UINT8: + toobig = dictLen > math.MaxUint8 + case arrow.INT8: + toobig = dictLen > math.MaxInt8 + case arrow.UINT16: + toobig = dictLen > math.MaxUint16 + case arrow.INT16: + toobig = dictLen > math.MaxInt16 + case arrow.UINT32: + toobig = uint(dictLen) > math.MaxUint32 + case arrow.INT32: + toobig = dictLen > math.MaxInt32 + case arrow.UINT64: + toobig = uint64(dictLen) > uint64(math.MaxUint64) + case arrow.INT64: + default: + return nil, fmt.Errorf("arrow/array: invalid dictionary index type: %s, must be integral", indexType) + } + if toobig { + return nil, errors.New("arrow/array: cannot combine dictionaries. unified dictionary requires a larger index type") + } + + dictData, err := GetDictArrayData(u.mem, arrow.BinaryTypes.Binary, u.memoTable, 0) + if err != nil { + return nil, err + } + + u.memoTable.Reset() + + defer dictData.Release() + return MakeFromData(dictData), nil +} + +func unifyRecursive(mem memory.Allocator, typ arrow.DataType, chunks []*Data) (changed bool, err error) { + debug.Assert(len(chunks) != 0, "must provide non-zero length chunk slice") + var extType arrow.DataType + + if typ.ID() == arrow.EXTENSION { + extType = typ + typ = typ.(arrow.ExtensionType).StorageType() + } + + if nestedTyp, ok := typ.(arrow.NestedType); ok { + children := make([]*Data, len(chunks)) + for i, f := range nestedTyp.Fields() { + for j, c := range chunks { + children[j] = c.childData[i].(*Data) + } + + childChanged, err := unifyRecursive(mem, f.Type, children) + if err != nil { + return false, err + } + if childChanged { + // only when unification actually occurs + for j := range chunks { + chunks[j].childData[i] = children[j] + } + changed = true + } + } + } + + if typ.ID() == arrow.DICTIONARY { + dictType := typ.(*arrow.DictionaryType) + var ( + uni DictionaryUnifier + newDict arrow.Array + ) + // unify any nested dictionaries first, but the unifier doesn't support + // nested dictionaries yet so this would fail. + uni, err = NewDictionaryUnifier(mem, dictType.ValueType) + if err != nil { + return changed, err + } + defer uni.Release() + transposeMaps := make([]*memory.Buffer, len(chunks)) + for i, c := range chunks { + debug.Assert(c.dictionary != nil, "missing dictionary data for dictionary array") + arr := MakeFromData(c.dictionary) + defer arr.Release() + if transposeMaps[i], err = uni.UnifyAndTranspose(arr); err != nil { + return + } + defer transposeMaps[i].Release() + } + + if newDict, err = uni.GetResultWithIndexType(dictType.IndexType); err != nil { + return + } + defer newDict.Release() + + for j := range chunks { + chnk, err := TransposeDictIndices(mem, chunks[j], typ, typ, newDict.Data(), arrow.Int32Traits.CastFromBytes(transposeMaps[j].Bytes())) + if err != nil { + return changed, err + } + chunks[j].Release() + chunks[j] = chnk.(*Data) + if extType != nil { + chunks[j].dtype = extType + } + } + changed = true + } + + return +} + +// UnifyChunkedDicts takes a chunked array of dictionary type and will unify +// the dictionary across all of the chunks with the returned chunked array +// having all chunks share the same dictionary. +// +// The return from this *must* have Release called on it unless an error is returned +// in which case the *arrow.Chunked will be nil. +// +// If there is 1 or fewer chunks, then nothing is modified and this function will just +// call Retain on the passed in Chunked array (so Release can safely be called on it). +// The same is true if the type of the array is not a dictionary or if no changes are +// needed for all of the chunks to be using the same dictionary. +func UnifyChunkedDicts(alloc memory.Allocator, chnkd *arrow.Chunked) (*arrow.Chunked, error) { + if len(chnkd.Chunks()) <= 1 { + chnkd.Retain() + return chnkd, nil + } + + chunksData := make([]*Data, len(chnkd.Chunks())) + for i, c := range chnkd.Chunks() { + c.Data().Retain() + chunksData[i] = c.Data().(*Data) + } + changed, err := unifyRecursive(alloc, chnkd.DataType(), chunksData) + if err != nil || !changed { + for _, c := range chunksData { + c.Release() + } + if err == nil { + chnkd.Retain() + } else { + chnkd = nil + } + return chnkd, err + } + + chunks := make([]arrow.Array, len(chunksData)) + for i, c := range chunksData { + chunks[i] = MakeFromData(c) + defer chunks[i].Release() + c.Release() + } + + return arrow.NewChunked(chnkd.DataType(), chunks), nil +} + +// UnifyTableDicts performs UnifyChunkedDicts on each column of the table so that +// any dictionary column will have the dictionaries of its chunks unified. +// +// The returned Table should always be Release'd unless a non-nil error was returned, +// in which case the table returned will be nil. +func UnifyTableDicts(alloc memory.Allocator, table arrow.Table) (arrow.Table, error) { + cols := make([]arrow.Column, table.NumCols()) + for i := 0; i < int(table.NumCols()); i++ { + chnkd, err := UnifyChunkedDicts(alloc, table.Column(i).Data()) + if err != nil { + return nil, err + } + defer chnkd.Release() + cols[i] = *arrow.NewColumn(table.Schema().Field(i), chnkd) + defer cols[i].Release() + } + return NewTable(table.Schema(), cols, table.NumRows()), nil +} + +var ( + _ arrow.Array = (*Dictionary)(nil) + _ Builder = (*dictionaryBuilder)(nil) +) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array/diff.go b/vendor/github.com/apache/arrow/go/v14/arrow/array/diff.go new file mode 100644 index 000000000..026a27b98 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array/diff.go @@ -0,0 +1,315 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package array + +import ( + "fmt" + "strings" + + "github.com/apache/arrow/go/v14/arrow" +) + +// Edit represents one entry in the edit script to compare two arrays. +type Edit struct { + Insert bool + RunLength int64 +} + +// Edits is a slice of Edit structs that represents an edit script to compare two arrays. +// When applied to the base array, it produces the target array. +// Each element of "insert" determines whether an element was inserted into (true) +// or deleted from (false) base. Each insertion or deletion is followed by a run of +// elements which are unchanged from base to target; the length of this run is stored +// in RunLength. (Note that the edit script begins and ends with a run of shared +// elements but both fields of the struct must have the same length. To accommodate this +// the first element of "insert" should be ignored.) +// +// For example for base "hlloo" and target "hello", the edit script would be +// [ +// +// {"insert": false, "run_length": 1}, // leading run of length 1 ("h") +// {"insert": true, "run_length": 3}, // insert("e") then a run of length 3 ("llo") +// {"insert": false, "run_length": 0} // delete("o") then an empty run +// +// ] +type Edits []Edit + +// String returns a simple string representation of the edit script. +func (e Edits) String() string { + return fmt.Sprintf("%v", []Edit(e)) +} + +// UnifiedDiff returns a string representation of the diff of base and target in Unified Diff format. +func (e Edits) UnifiedDiff(base, target arrow.Array) string { + var s strings.Builder + baseIndex := int64(0) + targetIndex := int64(0) + wrotePosition := false + for i := 0; i < len(e); i++ { + if i > 0 { + if !wrotePosition { + s.WriteString(fmt.Sprintf("@@ -%d, +%d @@\n", baseIndex, targetIndex)) + wrotePosition = true + } + if e[i].Insert { + s.WriteString(fmt.Sprintf("+%v\n", stringAt(target, targetIndex))) + targetIndex++ + } else { + s.WriteString(fmt.Sprintf("-%v\n", stringAt(base, baseIndex))) + baseIndex++ + } + } + for j := int64(0); j < e[i].RunLength; j++ { + baseIndex++ + targetIndex++ + wrotePosition = false + } + } + return s.String() +} + +func stringAt(arr arrow.Array, i int64) string { + if arr.IsNull(int(i)) { + return "null" + } + dt := arr.DataType() + switch { + case arrow.TypeEqual(dt, arrow.PrimitiveTypes.Float32): + return fmt.Sprintf("%f", arr.(*Float32).Value(int(i))) + case arrow.TypeEqual(dt, arrow.PrimitiveTypes.Float64): + return fmt.Sprintf("%f", arr.(*Float64).Value(int(i))) + case arrow.TypeEqual(dt, arrow.PrimitiveTypes.Date32): + return arr.(*Date32).Value(int(i)).FormattedString() + case arrow.TypeEqual(dt, arrow.PrimitiveTypes.Date64): + return arr.(*Date64).Value(int(i)).FormattedString() + case arrow.TypeEqual(dt, arrow.FixedWidthTypes.Timestamp_s): + return arr.(*Timestamp).Value(int(i)).ToTime(arrow.Second).String() + case arrow.TypeEqual(dt, arrow.FixedWidthTypes.Timestamp_ms): + return arr.(*Timestamp).Value(int(i)).ToTime(arrow.Millisecond).String() + case arrow.TypeEqual(dt, arrow.FixedWidthTypes.Timestamp_us): + return arr.(*Timestamp).Value(int(i)).ToTime(arrow.Microsecond).String() + case arrow.TypeEqual(dt, arrow.FixedWidthTypes.Timestamp_ns): + return arr.(*Timestamp).Value(int(i)).ToTime(arrow.Nanosecond).String() + } + s := NewSlice(arr, i, i+1) + defer s.Release() + st, _ := s.MarshalJSON() + return strings.Trim(string(st[1:len(st)-1]), "\n") +} + +// Diff compares two arrays, returning an edit script which expresses the difference +// between them. The edit script can be applied to the base array to produce the target. +// 'base' is a baseline for comparison. +// 'target' is an array of identical type to base whose elements differ from base's. +func Diff(base, target arrow.Array) (edits Edits, err error) { + if !arrow.TypeEqual(base.DataType(), target.DataType()) { + return nil, fmt.Errorf("%w: only taking the diff of like-typed arrays is supported", arrow.ErrNotImplemented) + } + switch base.DataType().ID() { + case arrow.EXTENSION: + return Diff(base.(ExtensionArray).Storage(), target.(ExtensionArray).Storage()) + case arrow.DICTIONARY: + return nil, fmt.Errorf("%w: diffing arrays of type %s is not implemented", arrow.ErrNotImplemented, base.DataType()) + case arrow.RUN_END_ENCODED: + return nil, fmt.Errorf("%w: diffing arrays of type %s is not implemented", arrow.ErrNotImplemented, base.DataType()) + } + d := newQuadraticSpaceMyersDiff(base, target) + return d.Diff() +} + +// editPoint represents an intermediate state in the comparison of two arrays +type editPoint struct { + base int + target int +} + +type quadraticSpaceMyersDiff struct { + base arrow.Array + target arrow.Array + finishIndex int + editCount int + endpointBase []int + insert []bool + baseBegin int + targetBegin int + baseEnd int + targetEnd int +} + +func newQuadraticSpaceMyersDiff(base, target arrow.Array) *quadraticSpaceMyersDiff { + d := &quadraticSpaceMyersDiff{ + base: base, + target: target, + finishIndex: -1, + editCount: 0, + endpointBase: []int{}, + insert: []bool{}, + baseBegin: 0, + targetBegin: 0, + baseEnd: base.Len(), + targetEnd: target.Len(), + } + d.endpointBase = []int{d.extendFrom(editPoint{d.baseBegin, d.targetBegin}).base} + if d.baseEnd-d.baseBegin == d.targetEnd-d.targetBegin && d.endpointBase[0] == d.baseEnd { + // trivial case: base == target + d.finishIndex = 0 + } + return d +} + +func (d *quadraticSpaceMyersDiff) valuesEqual(baseIndex, targetIndex int) bool { + baseNull := d.base.IsNull(baseIndex) + targetNull := d.target.IsNull(targetIndex) + if baseNull || targetNull { + return baseNull && targetNull + } + return SliceEqual(d.base, int64(baseIndex), int64(baseIndex+1), d.target, int64(targetIndex), int64(targetIndex+1)) +} + +// increment the position within base and target (the elements skipped in this way were +// present in both sequences) +func (d *quadraticSpaceMyersDiff) extendFrom(p editPoint) editPoint { + for p.base != d.baseEnd && p.target != d.targetEnd { + if !d.valuesEqual(p.base, p.target) { + break + } + p.base++ + p.target++ + } + return p +} + +// increment the position within base (the element pointed to was deleted) +// then extend maximally +func (d *quadraticSpaceMyersDiff) deleteOne(p editPoint) editPoint { + if p.base != d.baseEnd { + p.base++ + } + return d.extendFrom(p) +} + +// increment the position within target (the element pointed to was inserted) +// then extend maximally +func (d *quadraticSpaceMyersDiff) insertOne(p editPoint) editPoint { + if p.target != d.targetEnd { + p.target++ + } + return d.extendFrom(p) +} + +// beginning of a range for storing per-edit state in endpointBase and insert +func storageOffset(editCount int) int { + return editCount * (editCount + 1) / 2 +} + +// given edit_count and index, augment endpointBase[index] with the corresponding +// position in target (which is only implicitly represented in editCount, index) +func (d *quadraticSpaceMyersDiff) getEditPoint(editCount, index int) editPoint { + insertionsMinusDeletions := 2*(index-storageOffset(editCount)) - editCount + maximalBase := d.endpointBase[index] + maximalTarget := min(d.targetBegin+((maximalBase-d.baseBegin)+insertionsMinusDeletions), d.targetEnd) + return editPoint{maximalBase, maximalTarget} +} + +func (d *quadraticSpaceMyersDiff) Next() { + d.editCount++ + if len(d.endpointBase) < storageOffset(d.editCount+1) { + d.endpointBase = append(d.endpointBase, make([]int, storageOffset(d.editCount+1)-len(d.endpointBase))...) + } + if len(d.insert) < storageOffset(d.editCount+1) { + d.insert = append(d.insert, make([]bool, storageOffset(d.editCount+1)-len(d.insert))...) + } + previousOffset := storageOffset(d.editCount - 1) + currentOffset := storageOffset(d.editCount) + + // try deleting from base first + for i, iOut := 0, 0; i < d.editCount; i, iOut = i+1, iOut+1 { + previousEndpoint := d.getEditPoint(d.editCount-1, i+previousOffset) + d.endpointBase[iOut+currentOffset] = d.deleteOne(previousEndpoint).base + } + + // check if inserting from target could do better + for i, iOut := 0, 1; i < d.editCount; i, iOut = i+1, iOut+1 { + // retrieve the previously computed best endpoint for (editCount, iOut) + // for comparison with the best endpoint achievable with an insertion + endpointAfterDeletion := d.getEditPoint(d.editCount, iOut+currentOffset) + + previousEndpoint := d.getEditPoint(d.editCount-1, i+previousOffset) + endpointAfterInsertion := d.insertOne(previousEndpoint) + + if endpointAfterInsertion.base-endpointAfterDeletion.base >= 0 { + // insertion was more efficient; keep it and mark the insertion in insert + d.insert[iOut+currentOffset] = true + d.endpointBase[iOut+currentOffset] = endpointAfterInsertion.base + } + } + + finish := editPoint{d.baseEnd, d.targetEnd} + for iOut := 0; iOut < d.editCount+1; iOut++ { + if d.getEditPoint(d.editCount, iOut+currentOffset) == finish { + d.finishIndex = iOut + currentOffset + return + } + } +} + +func (d *quadraticSpaceMyersDiff) Done() bool { + return d.finishIndex != -1 +} + +func (d *quadraticSpaceMyersDiff) GetEdits() (Edits, error) { + if !d.Done() { + panic("GetEdits called but Done() = false") + } + + length := d.editCount + 1 + edits := make(Edits, length) + index := d.finishIndex + endpoint := d.getEditPoint(d.editCount, d.finishIndex) + + for i := d.editCount; i > 0; i-- { + insert := d.insert[index] + edits[i].Insert = insert + insertionsMinusDeletions := (endpoint.base - d.baseBegin) - (endpoint.target - d.targetBegin) + if insert { + insertionsMinusDeletions++ + } else { + insertionsMinusDeletions-- + } + index = (i-1-insertionsMinusDeletions)/2 + storageOffset(i-1) + + // endpoint of previous edit + previous := d.getEditPoint(i-1, index) + in := 0 + if insert { + in = 1 + } + edits[i].RunLength = int64(endpoint.base - previous.base - (1 - in)) + endpoint = previous + } + edits[0].Insert = false + edits[0].RunLength = int64(endpoint.base - d.baseBegin) + + return edits, nil +} + +func (d *quadraticSpaceMyersDiff) Diff() (edits Edits, err error) { + for !d.Done() { + d.Next() + } + return d.GetEdits() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array/doc.go b/vendor/github.com/apache/arrow/go/v14/arrow/array/doc.go new file mode 100644 index 000000000..5cf854086 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array/doc.go @@ -0,0 +1,20 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/* +Package array provides implementations of various Arrow array types. +*/ +package array diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array/encoded.go b/vendor/github.com/apache/arrow/go/v14/arrow/array/encoded.go new file mode 100644 index 000000000..bf4a942cf --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array/encoded.go @@ -0,0 +1,520 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package array + +import ( + "bytes" + "fmt" + "math" + "reflect" + "sync/atomic" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/encoded" + "github.com/apache/arrow/go/v14/arrow/internal/debug" + "github.com/apache/arrow/go/v14/arrow/memory" + "github.com/apache/arrow/go/v14/internal/json" + "github.com/apache/arrow/go/v14/internal/utils" +) + +// RunEndEncoded represents an array containing two children: +// an array of int32 values defining the ends of each run of values +// and an array of values +type RunEndEncoded struct { + array + + ends arrow.Array + values arrow.Array +} + +func NewRunEndEncodedArray(runEnds, values arrow.Array, logicalLength, offset int) *RunEndEncoded { + data := NewData(arrow.RunEndEncodedOf(runEnds.DataType(), values.DataType()), logicalLength, + []*memory.Buffer{nil}, []arrow.ArrayData{runEnds.Data(), values.Data()}, 0, offset) + defer data.Release() + return NewRunEndEncodedData(data) +} + +func NewRunEndEncodedData(data arrow.ArrayData) *RunEndEncoded { + r := &RunEndEncoded{} + r.refCount = 1 + r.setData(data.(*Data)) + return r +} + +func (r *RunEndEncoded) Values() arrow.Array { return r.values } +func (r *RunEndEncoded) RunEndsArr() arrow.Array { return r.ends } + +func (r *RunEndEncoded) Retain() { + r.array.Retain() + r.values.Retain() + r.ends.Retain() +} + +func (r *RunEndEncoded) Release() { + r.array.Release() + r.values.Release() + r.ends.Release() +} + +// LogicalValuesArray returns an array holding the values of each +// run, only over the range of run values inside the logical offset/length +// range of the parent array. +// +// # Example +// +// For this array: +// +// RunEndEncoded: { Offset: 150, Length: 1500 } +// RunEnds: [ 1, 2, 4, 6, 10, 1000, 1750, 2000 ] +// Values: [ "a", "b", "c", "d", "e", "f", "g", "h" ] +// +// LogicalValuesArray will return the following array: +// +// [ "f", "g" ] +// +// This is because the offset of 150 tells it to skip the values until +// "f" which corresponds with the logical offset (the run from 10 - 1000), +// and stops after "g" because the length + offset goes to 1650 which is +// within the run from 1000 - 1750, corresponding to the "g" value. +// +// # Note +// +// The return from this needs to be Released. +func (r *RunEndEncoded) LogicalValuesArray() arrow.Array { + physOffset := r.GetPhysicalOffset() + physLength := r.GetPhysicalLength() + data := NewSliceData(r.data.Children()[1], int64(physOffset), int64(physOffset+physLength)) + defer data.Release() + return MakeFromData(data) +} + +// LogicalRunEndsArray returns an array holding the logical indexes +// of each run end, only over the range of run end values relative +// to the logical offset/length range of the parent array. +// +// For arrays with an offset, this is not a slice of the existing +// internal run ends array. Instead a new array is created with run-ends +// that are adjusted so the new array can have an offset of 0. As a result +// this method can be expensive to call for an array with a non-zero offset. +// +// # Example +// +// For this array: +// +// RunEndEncoded: { Offset: 150, Length: 1500 } +// RunEnds: [ 1, 2, 4, 6, 10, 1000, 1750, 2000 ] +// Values: [ "a", "b", "c", "d", "e", "f", "g", "h" ] +// +// LogicalRunEndsArray will return the following array: +// +// [ 850, 1500 ] +// +// This is because the offset of 150 tells us to skip all run-ends less +// than 150 (by finding the physical offset), and we adjust the run-ends +// accordingly (1000 - 150 = 850). The logical length of the array is 1500, +// so we know we don't want to go past the 1750 run end. Thus the last +// run-end is determined by doing: min(1750 - 150, 1500) = 1500. +// +// # Note +// +// The return from this needs to be Released +func (r *RunEndEncoded) LogicalRunEndsArray(mem memory.Allocator) arrow.Array { + physOffset := r.GetPhysicalOffset() + physLength := r.GetPhysicalLength() + + if r.data.offset == 0 { + data := NewSliceData(r.data.childData[0], 0, int64(physLength)) + defer data.Release() + return MakeFromData(data) + } + + bldr := NewBuilder(mem, r.data.childData[0].DataType()) + defer bldr.Release() + bldr.Resize(physLength) + + switch e := r.ends.(type) { + case *Int16: + for _, v := range e.Int16Values()[physOffset : physOffset+physLength] { + v -= int16(r.data.offset) + v = int16(utils.MinInt(int(v), r.data.length)) + bldr.(*Int16Builder).Append(v) + } + case *Int32: + for _, v := range e.Int32Values()[physOffset : physOffset+physLength] { + v -= int32(r.data.offset) + v = int32(utils.MinInt(int(v), r.data.length)) + bldr.(*Int32Builder).Append(v) + } + case *Int64: + for _, v := range e.Int64Values()[physOffset : physOffset+physLength] { + v -= int64(r.data.offset) + v = int64(utils.MinInt(int(v), r.data.length)) + bldr.(*Int64Builder).Append(v) + } + } + + return bldr.NewArray() +} + +func (r *RunEndEncoded) setData(data *Data) { + if len(data.childData) != 2 { + panic(fmt.Errorf("%w: arrow/array: RLE array must have exactly 2 children", arrow.ErrInvalid)) + } + debug.Assert(data.dtype.ID() == arrow.RUN_END_ENCODED, "invalid type for RunLengthEncoded") + if !data.dtype.(*arrow.RunEndEncodedType).ValidRunEndsType(data.childData[0].DataType()) { + panic(fmt.Errorf("%w: arrow/array: run ends array must be int16, int32, or int64", arrow.ErrInvalid)) + } + if data.childData[0].NullN() > 0 { + panic(fmt.Errorf("%w: arrow/array: run ends array cannot contain nulls", arrow.ErrInvalid)) + } + + r.array.setData(data) + + r.ends = MakeFromData(r.data.childData[0]) + r.values = MakeFromData(r.data.childData[1]) +} + +func (r *RunEndEncoded) GetPhysicalOffset() int { + return encoded.FindPhysicalOffset(r.data) +} + +func (r *RunEndEncoded) GetPhysicalLength() int { + return encoded.GetPhysicalLength(r.data) +} + +// GetPhysicalIndex can be used to get the run-encoded value instead of costly LogicalValuesArray +// in the following way: +// +// r.Values().(valuetype).Value(r.GetPhysicalIndex(i)) +func (r *RunEndEncoded) GetPhysicalIndex(i int) int { + return encoded.FindPhysicalIndex(r.data, i+r.data.offset) +} + +// ValueStr will return the str representation of the value at the logical offset i. +func (r *RunEndEncoded) ValueStr(i int) string { + return r.values.ValueStr(r.GetPhysicalIndex(i)) +} + +func (r *RunEndEncoded) String() string { + var buf bytes.Buffer + buf.WriteByte('[') + for i := 0; i < r.ends.Len(); i++ { + if i != 0 { + buf.WriteByte(',') + } + + value := r.values.GetOneForMarshal(i) + if byts, ok := value.(json.RawMessage); ok { + value = string(byts) + } + fmt.Fprintf(&buf, "{%d -> %v}", r.ends.GetOneForMarshal(i), value) + } + + buf.WriteByte(']') + return buf.String() +} + +func (r *RunEndEncoded) GetOneForMarshal(i int) interface{} { + return r.values.GetOneForMarshal(r.GetPhysicalIndex(i)) +} + +func (r *RunEndEncoded) MarshalJSON() ([]byte, error) { + var buf bytes.Buffer + enc := json.NewEncoder(&buf) + buf.WriteByte('[') + for i := 0; i < r.Len(); i++ { + if i != 0 { + buf.WriteByte(',') + } + if err := enc.Encode(r.GetOneForMarshal(i)); err != nil { + return nil, err + } + } + buf.WriteByte(']') + return buf.Bytes(), nil +} + +func arrayRunEndEncodedEqual(l, r *RunEndEncoded) bool { + // types were already checked before getting here, so we know + // the encoded types are equal + mr := encoded.NewMergedRuns([2]arrow.Array{l, r}) + for mr.Next() { + lIndex := mr.IndexIntoArray(0) + rIndex := mr.IndexIntoArray(1) + if !SliceEqual(l.values, lIndex, lIndex+1, r.values, rIndex, rIndex+1) { + return false + } + } + return true +} + +func arrayRunEndEncodedApproxEqual(l, r *RunEndEncoded, opt equalOption) bool { + // types were already checked before getting here, so we know + // the encoded types are equal + mr := encoded.NewMergedRuns([2]arrow.Array{l, r}) + for mr.Next() { + lIndex := mr.IndexIntoArray(0) + rIndex := mr.IndexIntoArray(1) + if !sliceApproxEqual(l.values, lIndex, lIndex+1, r.values, rIndex, rIndex+1, opt) { + return false + } + } + return true +} + +type RunEndEncodedBuilder struct { + builder + + dt arrow.DataType + runEnds Builder + values Builder + maxRunEnd uint64 + + // currently, mixing AppendValueFromString & UnmarshalOne is unsupported + lastUnmarshalled interface{} + unmarshalled bool // tracks if Unmarshal was called (in case lastUnmarshalled is nil) + lastStr *string +} + +func NewRunEndEncodedBuilder(mem memory.Allocator, runEnds, encoded arrow.DataType) *RunEndEncodedBuilder { + dt := arrow.RunEndEncodedOf(runEnds, encoded) + if !dt.ValidRunEndsType(runEnds) { + panic("arrow/ree: invalid runEnds type for run length encoded array") + } + + var maxEnd uint64 + switch runEnds.ID() { + case arrow.INT16: + maxEnd = math.MaxInt16 + case arrow.INT32: + maxEnd = math.MaxInt32 + case arrow.INT64: + maxEnd = math.MaxInt64 + } + return &RunEndEncodedBuilder{ + builder: builder{refCount: 1, mem: mem}, + dt: dt, + runEnds: NewBuilder(mem, runEnds), + values: NewBuilder(mem, encoded), + maxRunEnd: maxEnd, + lastUnmarshalled: nil, + } +} + +func (b *RunEndEncodedBuilder) Type() arrow.DataType { + return b.dt +} + +func (b *RunEndEncodedBuilder) Release() { + debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases") + + if atomic.AddInt64(&b.refCount, -1) == 0 { + b.values.Release() + b.runEnds.Release() + } +} + +func (b *RunEndEncodedBuilder) addLength(n uint64) { + if uint64(b.length)+n > b.maxRunEnd { + panic(fmt.Errorf("%w: %s array length must fit be less than %d", arrow.ErrInvalid, b.dt, b.maxRunEnd)) + } + + b.length += int(n) +} + +func (b *RunEndEncodedBuilder) finishRun() { + b.lastUnmarshalled = nil + b.lastStr = nil + b.unmarshalled = false + if b.length == 0 { + return + } + + switch bldr := b.runEnds.(type) { + case *Int16Builder: + bldr.Append(int16(b.length)) + case *Int32Builder: + bldr.Append(int32(b.length)) + case *Int64Builder: + bldr.Append(int64(b.length)) + } +} + +func (b *RunEndEncodedBuilder) ValueBuilder() Builder { return b.values } + +func (b *RunEndEncodedBuilder) Append(n uint64) { + b.finishRun() + b.addLength(n) +} + +func (b *RunEndEncodedBuilder) AppendRuns(runs []uint64) { + for _, r := range runs { + b.finishRun() + b.addLength(r) + } +} + +func (b *RunEndEncodedBuilder) ContinueRun(n uint64) { + b.addLength(n) +} + +func (b *RunEndEncodedBuilder) AppendNull() { + b.finishRun() + b.values.AppendNull() + b.addLength(1) +} + +func (b *RunEndEncodedBuilder) AppendNulls(n int) { + for i := 0; i < n; i++ { + b.AppendNull() + } +} + +func (b *RunEndEncodedBuilder) NullN() int { + return UnknownNullCount +} + +func (b *RunEndEncodedBuilder) AppendEmptyValue() { + b.AppendNull() +} + +func (b *RunEndEncodedBuilder) AppendEmptyValues(n int) { + b.AppendNulls(n) +} + +func (b *RunEndEncodedBuilder) Reserve(n int) { + b.values.Reserve(n) + b.runEnds.Reserve(n) +} + +func (b *RunEndEncodedBuilder) Resize(n int) { + b.values.Resize(n) + b.runEnds.Resize(n) +} + +func (b *RunEndEncodedBuilder) NewRunEndEncodedArray() *RunEndEncoded { + data := b.newData() + defer data.Release() + return NewRunEndEncodedData(data) +} + +func (b *RunEndEncodedBuilder) NewArray() arrow.Array { + return b.NewRunEndEncodedArray() +} + +func (b *RunEndEncodedBuilder) newData() (data *Data) { + b.finishRun() + values := b.values.NewArray() + defer values.Release() + runEnds := b.runEnds.NewArray() + defer runEnds.Release() + + data = NewData( + b.dt, b.length, []*memory.Buffer{}, + []arrow.ArrayData{runEnds.Data(), values.Data()}, 0, 0) + b.reset() + return +} + +// AppendValueFromString can't be used in conjunction with UnmarshalOne +func (b *RunEndEncodedBuilder) AppendValueFromString(s string) error { + // we don't support mixing AppendValueFromString & UnmarshalOne + if b.unmarshalled { + return fmt.Errorf("%w: mixing AppendValueFromString & UnmarshalOne not yet implemented", arrow.ErrNotImplemented) + } + + if s == NullValueStr { + b.AppendNull() + return nil + } + + if b.lastStr != nil && s == *b.lastStr { + b.ContinueRun(1) + return nil + } + + b.Append(1) + lastStr := s + b.lastStr = &lastStr + return b.ValueBuilder().AppendValueFromString(s) +} + +// UnmarshalOne can't be used in conjunction with AppendValueFromString +func (b *RunEndEncodedBuilder) UnmarshalOne(dec *json.Decoder) error { + // we don't support mixing AppendValueFromString & UnmarshalOne + if b.lastStr != nil { + return fmt.Errorf("%w: mixing AppendValueFromString & UnmarshalOne not yet implemented", arrow.ErrNotImplemented) + } + + var value interface{} + if err := dec.Decode(&value); err != nil { + return err + } + + // if we unmarshalled the same value as the previous one, we want to + // continue the run. However, there's an edge case. At the start of + // unmarshalling, lastUnmarshalled will be nil, but we might get + // nil as the first value we unmarshal. In that case we want to + // make sure we add a new run instead. We can detect that case by + // checking that the number of runEnds matches the number of values + // we have, which means no matter what we have to start a new run + if reflect.DeepEqual(value, b.lastUnmarshalled) && (value != nil || b.runEnds.Len() != b.values.Len()) { + b.ContinueRun(1) + return nil + } + + data, err := json.Marshal(value) + if err != nil { + return err + } + + b.Append(1) + b.lastUnmarshalled = value + b.unmarshalled = true + return b.ValueBuilder().UnmarshalOne(json.NewDecoder(bytes.NewReader(data))) +} + +// Unmarshal can't be used in conjunction with AppendValueFromString (as it calls UnmarshalOne) +func (b *RunEndEncodedBuilder) Unmarshal(dec *json.Decoder) error { + b.finishRun() + for dec.More() { + if err := b.UnmarshalOne(dec); err != nil { + return err + } + } + return nil +} + +// UnmarshalJSON can't be used in conjunction with AppendValueFromString (as it calls UnmarshalOne) +func (b *RunEndEncodedBuilder) UnmarshalJSON(data []byte) error { + dec := json.NewDecoder(bytes.NewReader(data)) + t, err := dec.Token() + if err != nil { + return err + } + + if delim, ok := t.(json.Delim); !ok || delim != '[' { + return fmt.Errorf("list builder must unpack from json array, found %s", delim) + } + + return b.Unmarshal(dec) +} + +var ( + _ arrow.Array = (*RunEndEncoded)(nil) + _ Builder = (*RunEndEncodedBuilder)(nil) +) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array/extension.go b/vendor/github.com/apache/arrow/go/v14/arrow/array/extension.go new file mode 100644 index 000000000..03e8c1734 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array/extension.go @@ -0,0 +1,244 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package array + +import ( + "fmt" + "reflect" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/memory" + "github.com/apache/arrow/go/v14/internal/json" +) + +// ExtensionArray is the interface that needs to be implemented to handle +// user-defined extension type arrays. In order to ensure consistency and +// proper behavior, all ExtensionArray types must embed ExtensionArrayBase +// in order to meet the interface which provides the default implementation +// and handling for the array while allowing custom behavior to be built +// on top of it. +type ExtensionArray interface { + arrow.Array + // ExtensionType returns the datatype as per calling DataType(), but + // already cast to ExtensionType + ExtensionType() arrow.ExtensionType + // Storage returns the underlying storage array for this array. + Storage() arrow.Array + // by having a non-exported function in the interface, it means that + // consumers must embed ExtensionArrayBase in their structs in order + // to fulfill this interface. + mustEmbedExtensionArrayBase() +} + +// two extension arrays are equal if their data types are equal and +// their underlying storage arrays are equal. +func arrayEqualExtension(l, r ExtensionArray) bool { + if !arrow.TypeEqual(l.DataType(), r.DataType()) { + return false + } + + return Equal(l.Storage(), r.Storage()) +} + +// two extension arrays are approximately equal if their data types are +// equal and their underlying storage arrays are approximately equal. +func arrayApproxEqualExtension(l, r ExtensionArray, opt equalOption) bool { + if !arrow.TypeEqual(l.DataType(), r.DataType()) { + return false + } + + return arrayApproxEqual(l.Storage(), r.Storage(), opt) +} + +// NewExtensionArrayWithStorage constructs a new ExtensionArray from the provided +// ExtensionType and uses the provided storage interface as the underlying storage. +// This will not release the storage array passed in so consumers should call Release +// on it manually while the new Extension array will share references to the underlying +// Data buffers. +func NewExtensionArrayWithStorage(dt arrow.ExtensionType, storage arrow.Array) arrow.Array { + if !arrow.TypeEqual(dt.StorageType(), storage.DataType()) { + panic(fmt.Errorf("arrow/array: storage type %s for extension type %s, does not match expected type %s", storage.DataType(), dt.ExtensionName(), dt.StorageType())) + } + + storageData := storage.Data().(*Data) + // create a new data instance with the ExtensionType as the datatype but referencing the + // same underlying buffers to share them with the storage array. + data := NewData(dt, storageData.length, storageData.buffers, storageData.childData, storageData.nulls, storageData.offset) + defer data.Release() + return NewExtensionData(data) +} + +// NewExtensionData expects a data with a datatype of arrow.ExtensionType and +// underlying data built for the storage array. +func NewExtensionData(data arrow.ArrayData) ExtensionArray { + base := ExtensionArrayBase{} + base.refCount = 1 + base.setData(data.(*Data)) + + // use the ExtensionType's ArrayType to construct the correctly typed object + // to use as the ExtensionArray interface. reflect.New returns a pointer to + // the newly created object. + arr := reflect.New(base.ExtensionType().ArrayType()) + // set the embedded ExtensionArrayBase to the value we created above. We know + // that this field will exist because the interface requires embedding ExtensionArrayBase + // so we don't have to separately check, this will panic if called on an ArrayType + // that doesn't embed ExtensionArrayBase which is what we want. + arr.Elem().FieldByName("ExtensionArrayBase").Set(reflect.ValueOf(base)) + return arr.Interface().(ExtensionArray) +} + +// ExtensionArrayBase is the base struct for user-defined Extension Array types +// and must be embedded in any user-defined extension arrays like so: +// +// type UserDefinedArray struct { +// array.ExtensionArrayBase +// } +type ExtensionArrayBase struct { + array + storage arrow.Array +} + +func (e *ExtensionArrayBase) String() string { + return fmt.Sprintf("(%s)%s", e.data.dtype, e.storage) +} + +func (e *ExtensionArrayBase) GetOneForMarshal(i int) interface{} { + return e.storage.GetOneForMarshal(i) +} + +func (e *ExtensionArrayBase) MarshalJSON() ([]byte, error) { + return json.Marshal(e.storage) +} + +// Retain increases the reference count by 1. +// Retain may be called simultaneously from multiple goroutines. +func (e *ExtensionArrayBase) Retain() { + e.array.Retain() + e.storage.Retain() +} + +// Release decreases the reference count by 1. +// Release may be called simultaneously from multiple goroutines. +// When the reference count goes to zero, the memory is freed. +func (e *ExtensionArrayBase) Release() { + e.array.Release() + e.storage.Release() +} + +// Storage returns the underlying storage array +func (e *ExtensionArrayBase) Storage() arrow.Array { return e.storage } + +// ExtensionType returns the same thing as DataType, just already casted +// to an ExtensionType interface for convenience. +func (e *ExtensionArrayBase) ExtensionType() arrow.ExtensionType { + return e.DataType().(arrow.ExtensionType) +} + +func (e *ExtensionArrayBase) setData(data *Data) { + if data.DataType().ID() != arrow.EXTENSION { + panic("arrow/array: must use extension type to construct an extension array") + } + extType, ok := data.dtype.(arrow.ExtensionType) + if !ok { + panic("arrow/array: DataType for ExtensionArray must implement arrow.ExtensionType") + } + + e.array.setData(data) + // our underlying storage needs to reference the same data buffers (no copying) + // but should have the storage type's datatype, so we create a Data for it. + storageData := NewData(extType.StorageType(), data.length, data.buffers, data.childData, data.nulls, data.offset) + storageData.SetDictionary(data.dictionary) + defer storageData.Release() + e.storage = MakeFromData(storageData) +} + +// ValueStr returns the value at index i as a string. +// This needs to be implemented by the extension array type. +func (e *ExtensionArrayBase) ValueStr(i int) string { + panic("arrow/array: ValueStr wasn't implemented by this extension array type") +} + +// no-op function that exists simply to force embedding this in any extension array types. +func (ExtensionArrayBase) mustEmbedExtensionArrayBase() {} + +// ExtensionBuilder is a convenience builder so that NewBuilder and such will still work +// with extension types properly. Depending on preference it may be cleaner or easier to just use +// NewExtensionArrayWithStorage and pass a storage array. +// +// That said, this allows easily building an extension array by providing the extension +// type and retrieving the storage builder. +type ExtensionBuilder struct { + Builder + dt arrow.ExtensionType +} + +// NewExtensionBuilder returns a builder using the provided memory allocator for the desired +// extension type. It will internally construct a builder of the storage type for the extension +// type and keep a copy of the extension type. The underlying type builder can then be retrieved +// by calling `StorageBuilder` on this and then type asserting it to the desired builder type. +// +// After using the storage builder, calling NewArray or NewExtensionArray will construct +// the appropriate extension array type and set the storage correctly, resetting the builder for +// reuse. +// +// # Example +// +// Simple example assuming an extension type of a UUID defined as a FixedSizeBinary(16) was registered +// using the type name "uuid": +// +// uuidType := arrow.GetExtensionType("uuid") +// bldr := array.NewExtensionBuilder(memory.DefaultAllocator, uuidType) +// defer bldr.Release() +// uuidBldr := bldr.StorageBuilder().(*array.FixedSizeBinaryBuilder) +// /* build up the fixed size binary array as usual via Append/AppendValues */ +// uuidArr := bldr.NewExtensionArray() +// defer uuidArr.Release() +// +// Because the storage builder is embedded in the Extension builder it also means +// that any of the functions available on the Builder interface can be called on +// an instance of ExtensionBuilder and will respond appropriately as the storage +// builder would for generically grabbing the Lenth, Cap, Nulls, reserving, etc. +func NewExtensionBuilder(mem memory.Allocator, dt arrow.ExtensionType) *ExtensionBuilder { + return &ExtensionBuilder{Builder: NewBuilder(mem, dt.StorageType()), dt: dt} +} + +func (b *ExtensionBuilder) Type() arrow.DataType { return b.dt } + +// StorageBuilder returns the builder for the underlying storage type. +func (b *ExtensionBuilder) StorageBuilder() Builder { return b.Builder } + +// NewArray creates a new array from the memory buffers used by the builder +// and resets the builder so it can be used to build a new array. +func (b *ExtensionBuilder) NewArray() arrow.Array { + return b.NewExtensionArray() +} + +// NewExtensionArray creates an Extension array from the memory buffers used +// by the builder and resets the ExtensionBuilder so it can be used to build +// a new ExtensionArray of the same type. +func (b *ExtensionBuilder) NewExtensionArray() ExtensionArray { + storage := b.Builder.NewArray() + defer storage.Release() + + storage.Data().(*Data).dtype = b.dt + return NewExtensionData(storage.Data()) +} + +var ( + _ arrow.Array = (ExtensionArray)(nil) + _ Builder = (*ExtensionBuilder)(nil) +) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array/extension_builder.go b/vendor/github.com/apache/arrow/go/v14/arrow/array/extension_builder.go new file mode 100644 index 000000000..a71287faf --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array/extension_builder.go @@ -0,0 +1,23 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package array + +// ExtensionBuilderWrapper is an interface that you need to implement in your custom extension type if you want to provide a customer builder as well. +// See example in ./arrow/internal/testing/types/extension_types.go +type ExtensionBuilderWrapper interface { + NewBuilder(bldr *ExtensionBuilder) Builder +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array/fixed_size_list.go b/vendor/github.com/apache/arrow/go/v14/arrow/array/fixed_size_list.go new file mode 100644 index 000000000..62c321386 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array/fixed_size_list.go @@ -0,0 +1,372 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package array + +import ( + "bytes" + "fmt" + "strings" + "sync/atomic" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/bitutil" + "github.com/apache/arrow/go/v14/arrow/internal/debug" + "github.com/apache/arrow/go/v14/arrow/memory" + "github.com/apache/arrow/go/v14/internal/json" +) + +// FixedSizeList represents an immutable sequence of N array values. +type FixedSizeList struct { + array + n int32 + values arrow.Array +} + +var _ ListLike = (*FixedSizeList)(nil) + +// NewFixedSizeListData returns a new List array value, from data. +func NewFixedSizeListData(data arrow.ArrayData) *FixedSizeList { + a := &FixedSizeList{} + a.refCount = 1 + a.setData(data.(*Data)) + return a +} + +func (a *FixedSizeList) ListValues() arrow.Array { return a.values } + +func (a *FixedSizeList) ValueStr(i int) string { + if a.IsNull(i) { + return NullValueStr + } + return string(a.GetOneForMarshal(i).(json.RawMessage)) +} +func (a *FixedSizeList) String() string { + o := new(strings.Builder) + o.WriteString("[") + for i := 0; i < a.Len(); i++ { + if i > 0 { + o.WriteString(" ") + } + if !a.IsValid(i) { + o.WriteString(NullValueStr) + continue + } + sub := a.newListValue(i) + fmt.Fprintf(o, "%v", sub) + sub.Release() + } + o.WriteString("]") + return o.String() +} + +func (a *FixedSizeList) newListValue(i int) arrow.Array { + beg, end := a.ValueOffsets(i) + return NewSlice(a.values, beg, end) +} + +func (a *FixedSizeList) setData(data *Data) { + a.array.setData(data) + a.n = a.DataType().(*arrow.FixedSizeListType).Len() + a.values = MakeFromData(data.childData[0]) +} + +func arrayEqualFixedSizeList(left, right *FixedSizeList) bool { + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + o := func() bool { + l := left.newListValue(i) + defer l.Release() + r := right.newListValue(i) + defer r.Release() + return Equal(l, r) + }() + if !o { + return false + } + } + return true +} + +// Len returns the number of elements in the array. +func (a *FixedSizeList) Len() int { return a.array.Len() } + +func (a *FixedSizeList) ValueOffsets(i int) (start, end int64) { + n := int64(a.n) + off := int64(a.array.data.offset) + start, end = (off+int64(i))*n, (off+int64(i+1))*n + return +} + +func (a *FixedSizeList) Retain() { + a.array.Retain() + a.values.Retain() +} + +func (a *FixedSizeList) Release() { + a.array.Release() + a.values.Release() +} + +func (a *FixedSizeList) GetOneForMarshal(i int) interface{} { + if a.IsNull(i) { + return nil + } + slice := a.newListValue(i) + defer slice.Release() + v, err := json.Marshal(slice) + if err != nil { + panic(err) + } + + return json.RawMessage(v) +} + +func (a *FixedSizeList) MarshalJSON() ([]byte, error) { + var buf bytes.Buffer + enc := json.NewEncoder(&buf) + + buf.WriteByte('[') + for i := 0; i < a.Len(); i++ { + if i != 0 { + buf.WriteByte(',') + } + if a.IsNull(i) { + enc.Encode(nil) + continue + } + + slice := a.newListValue(i) + if err := enc.Encode(slice); err != nil { + return nil, err + } + slice.Release() + } + buf.WriteByte(']') + return buf.Bytes(), nil +} + +type FixedSizeListBuilder struct { + builder + + etype arrow.DataType // data type of the list's elements. + n int32 // number of elements in the fixed-size list. + values Builder // value builder for the list's elements. +} + +// NewFixedSizeListBuilder returns a builder, using the provided memory allocator. +// The created list builder will create a list whose elements will be of type etype. +func NewFixedSizeListBuilder(mem memory.Allocator, n int32, etype arrow.DataType) *FixedSizeListBuilder { + return &FixedSizeListBuilder{ + builder: builder{refCount: 1, mem: mem}, + etype: etype, + n: n, + values: NewBuilder(mem, etype), + } +} + +func (b *FixedSizeListBuilder) Type() arrow.DataType { return arrow.FixedSizeListOf(b.n, b.etype) } + +// Release decreases the reference count by 1. +// When the reference count goes to zero, the memory is freed. +func (b *FixedSizeListBuilder) Release() { + debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases") + + if atomic.AddInt64(&b.refCount, -1) == 0 { + if b.nullBitmap != nil { + b.nullBitmap.Release() + b.nullBitmap = nil + } + if b.values != nil { + b.values.Release() + b.values = nil + } + } +} + +func (b *FixedSizeListBuilder) Append(v bool) { + b.Reserve(1) + b.unsafeAppendBoolToBitmap(v) +} + +// AppendNull will append null values to the underlying values by itself +func (b *FixedSizeListBuilder) AppendNull() { + b.Reserve(1) + b.unsafeAppendBoolToBitmap(false) + // require to append this due to value indexes + for i := int32(0); i < b.n; i++ { + b.values.AppendNull() + } +} + +// AppendNulls will append n null values to the underlying values by itself +func (b *FixedSizeListBuilder) AppendNulls(n int) { + for i := 0; i < n; i++ { + b.AppendNull() + } +} + +func (b *FixedSizeListBuilder) AppendEmptyValue() { + b.Append(true) + for i := int32(0); i < b.n; i++ { + b.values.AppendEmptyValue() + } +} + +func (b *FixedSizeListBuilder) AppendEmptyValues(n int) { + for i := 0; i < n; i++ { + b.AppendEmptyValue() + } +} + +func (b *FixedSizeListBuilder) AppendValues(valid []bool) { + b.Reserve(len(valid)) + b.builder.unsafeAppendBoolsToBitmap(valid, len(valid)) +} + +func (b *FixedSizeListBuilder) unsafeAppendBoolToBitmap(isValid bool) { + if isValid { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + } else { + b.nulls++ + } + b.length++ +} + +func (b *FixedSizeListBuilder) init(capacity int) { + b.builder.init(capacity) +} + +// Reserve ensures there is enough space for appending n elements +// by checking the capacity and calling Resize if necessary. +func (b *FixedSizeListBuilder) Reserve(n int) { + b.builder.reserve(n, b.Resize) +} + +// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(), +// additional memory will be allocated. If n is smaller, the allocated memory may reduced. +func (b *FixedSizeListBuilder) Resize(n int) { + if n < minBuilderCapacity { + n = minBuilderCapacity + } + + if b.capacity == 0 { + b.init(n) + } else { + b.builder.resize(n, b.builder.init) + } +} + +func (b *FixedSizeListBuilder) ValueBuilder() Builder { + return b.values +} + +// NewArray creates a List array from the memory buffers used by the builder and resets the FixedSizeListBuilder +// so it can be used to build a new array. +func (b *FixedSizeListBuilder) NewArray() arrow.Array { + return b.NewListArray() +} + +// NewListArray creates a List array from the memory buffers used by the builder and resets the FixedSizeListBuilder +// so it can be used to build a new array. +func (b *FixedSizeListBuilder) NewListArray() (a *FixedSizeList) { + data := b.newData() + a = NewFixedSizeListData(data) + data.Release() + return +} + +func (b *FixedSizeListBuilder) newData() (data *Data) { + values := b.values.NewArray() + defer values.Release() + + data = NewData( + arrow.FixedSizeListOf(b.n, b.etype), b.length, + []*memory.Buffer{b.nullBitmap}, + []arrow.ArrayData{values.Data()}, + b.nulls, + 0, + ) + b.reset() + + return +} + +func (b *FixedSizeListBuilder) AppendValueFromString(s string) error { + if s == NullValueStr { + b.AppendNull() + return nil + } + dec := json.NewDecoder(strings.NewReader(s)) + return b.UnmarshalOne(dec) +} + +func (b *FixedSizeListBuilder) UnmarshalOne(dec *json.Decoder) error { + t, err := dec.Token() + if err != nil { + return err + } + + switch t { + case json.Delim('['): + b.Append(true) + if err := b.values.Unmarshal(dec); err != nil { + return err + } + // consume ']' + _, err := dec.Token() + return err + case nil: + b.AppendNull() + default: + return &json.UnmarshalTypeError{ + Value: fmt.Sprint(t), + Struct: arrow.FixedSizeListOf(b.n, b.etype).String(), + } + } + + return nil +} + +func (b *FixedSizeListBuilder) Unmarshal(dec *json.Decoder) error { + for dec.More() { + if err := b.UnmarshalOne(dec); err != nil { + return err + } + } + return nil +} + +func (b *FixedSizeListBuilder) UnmarshalJSON(data []byte) error { + dec := json.NewDecoder(bytes.NewReader(data)) + t, err := dec.Token() + if err != nil { + return err + } + + if delim, ok := t.(json.Delim); !ok || delim != '[' { + return fmt.Errorf("fixed size list builder must unpack from json array, found %s", delim) + } + + return b.Unmarshal(dec) +} + +var ( + _ arrow.Array = (*FixedSizeList)(nil) + _ Builder = (*FixedSizeListBuilder)(nil) +) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array/fixedsize_binary.go b/vendor/github.com/apache/arrow/go/v14/arrow/array/fixedsize_binary.go new file mode 100644 index 000000000..5466156d5 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array/fixedsize_binary.go @@ -0,0 +1,123 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package array + +import ( + "bytes" + "encoding/base64" + "fmt" + "strings" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/internal/json" +) + +// A type which represents an immutable sequence of fixed-length binary strings. +type FixedSizeBinary struct { + array + + valueBytes []byte + bytewidth int32 +} + +// NewFixedSizeBinaryData constructs a new fixed-size binary array from data. +func NewFixedSizeBinaryData(data arrow.ArrayData) *FixedSizeBinary { + a := &FixedSizeBinary{bytewidth: int32(data.DataType().(arrow.FixedWidthDataType).BitWidth() / 8)} + a.refCount = 1 + a.setData(data.(*Data)) + return a +} + +// Value returns the fixed-size slice at index i. This value should not be mutated. +func (a *FixedSizeBinary) Value(i int) []byte { + i += a.array.data.offset + var ( + bw = int(a.bytewidth) + beg = i * bw + end = (i + 1) * bw + ) + return a.valueBytes[beg:end] +} +func (a *FixedSizeBinary) ValueStr(i int) string { + if a.IsNull(i) { + return NullValueStr + } + return base64.StdEncoding.EncodeToString(a.Value(i)) +} + +func (a *FixedSizeBinary) String() string { + o := new(strings.Builder) + o.WriteString("[") + for i := 0; i < a.Len(); i++ { + if i > 0 { + o.WriteString(" ") + } + switch { + case a.IsNull(i): + o.WriteString(NullValueStr) + default: + fmt.Fprintf(o, "%q", a.Value(i)) + } + } + o.WriteString("]") + return o.String() +} + +func (a *FixedSizeBinary) setData(data *Data) { + a.array.setData(data) + vals := data.buffers[1] + if vals != nil { + a.valueBytes = vals.Bytes() + } + +} + +func (a *FixedSizeBinary) GetOneForMarshal(i int) interface{} { + if a.IsNull(i) { + return nil + } + + return a.Value(i) +} + +func (a *FixedSizeBinary) MarshalJSON() ([]byte, error) { + vals := make([]interface{}, a.Len()) + for i := 0; i < a.Len(); i++ { + if a.IsValid(i) { + vals[i] = a.Value(i) + } else { + vals[i] = nil + } + } + return json.Marshal(vals) +} + +func arrayEqualFixedSizeBinary(left, right *FixedSizeBinary) bool { + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + if !bytes.Equal(left.Value(i), right.Value(i)) { + return false + } + } + return true +} + +var ( + _ arrow.Array = (*FixedSizeBinary)(nil) +) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array/fixedsize_binarybuilder.go b/vendor/github.com/apache/arrow/go/v14/arrow/array/fixedsize_binarybuilder.go new file mode 100644 index 000000000..ba4b474a8 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array/fixedsize_binarybuilder.go @@ -0,0 +1,261 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package array + +import ( + "bytes" + "encoding/base64" + "fmt" + "reflect" + "sync/atomic" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/internal/debug" + "github.com/apache/arrow/go/v14/arrow/memory" + "github.com/apache/arrow/go/v14/internal/json" +) + +// A FixedSizeBinaryBuilder is used to build a FixedSizeBinary array using the Append methods. +type FixedSizeBinaryBuilder struct { + builder + + dtype *arrow.FixedSizeBinaryType + values *byteBufferBuilder +} + +func NewFixedSizeBinaryBuilder(mem memory.Allocator, dtype *arrow.FixedSizeBinaryType) *FixedSizeBinaryBuilder { + b := &FixedSizeBinaryBuilder{ + builder: builder{refCount: 1, mem: mem}, + dtype: dtype, + values: newByteBufferBuilder(mem), + } + return b +} + +func (b *FixedSizeBinaryBuilder) Type() arrow.DataType { return b.dtype } + +// Release decreases the reference count by 1. +// When the reference count goes to zero, the memory is freed. +// Release may be called simultaneously from multiple goroutines. +func (b *FixedSizeBinaryBuilder) Release() { + debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases") + + if atomic.AddInt64(&b.refCount, -1) == 0 { + if b.nullBitmap != nil { + b.nullBitmap.Release() + b.nullBitmap = nil + } + if b.values != nil { + b.values.Release() + b.values = nil + } + } +} + +func (b *FixedSizeBinaryBuilder) Append(v []byte) { + if len(v) != b.dtype.ByteWidth { + // TODO(alexandre): should we return an error instead? + panic("len(v) != b.dtype.ByteWidth") + } + + b.Reserve(1) + b.values.Append(v) + b.UnsafeAppendBoolToBitmap(true) +} + +func (b *FixedSizeBinaryBuilder) AppendNull() { + b.Reserve(1) + b.values.Advance(b.dtype.ByteWidth) + b.UnsafeAppendBoolToBitmap(false) +} + +func (b *FixedSizeBinaryBuilder) AppendNulls(n int) { + for i := 0; i < n; i++ { + b.AppendNull() + } +} + +func (b *FixedSizeBinaryBuilder) AppendEmptyValue() { + b.Reserve(1) + b.values.Advance(b.dtype.ByteWidth) + b.UnsafeAppendBoolToBitmap(true) +} + +func (b *FixedSizeBinaryBuilder) AppendEmptyValues(n int) { + for i := 0; i < n; i++ { + b.AppendEmptyValue() + } +} + +func (b *FixedSizeBinaryBuilder) UnsafeAppend(v []byte) { + b.values.unsafeAppend(v) + b.UnsafeAppendBoolToBitmap(true) +} + +// AppendValues will append the values in the v slice. The valid slice determines which values +// in v are valid (not null). The valid slice must either be empty or be equal in length to v. If empty, +// all values in v are appended and considered valid. +func (b *FixedSizeBinaryBuilder) AppendValues(v [][]byte, valid []bool) { + if len(v) != len(valid) && len(valid) != 0 { + panic("len(v) != len(valid) && len(valid) != 0") + } + + if len(v) == 0 { + return + } + + b.Reserve(len(v)) + for _, vv := range v { + switch len(vv) { + case 0: + b.values.Advance(b.dtype.ByteWidth) + case b.dtype.ByteWidth: + b.values.Append(vv) + default: + panic(fmt.Errorf("array: invalid binary length (got=%d, want=%d)", len(vv), b.dtype.ByteWidth)) + } + } + + b.builder.unsafeAppendBoolsToBitmap(valid, len(v)) +} + +func (b *FixedSizeBinaryBuilder) init(capacity int) { + b.builder.init(capacity) + b.values.resize(capacity * b.dtype.ByteWidth) +} + +// Reserve ensures there is enough space for appending n elements +// by checking the capacity and calling Resize if necessary. +func (b *FixedSizeBinaryBuilder) Reserve(n int) { + b.builder.reserve(n, b.Resize) +} + +// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(), +// additional memory will be allocated. If n is smaller, the allocated memory may reduced. +func (b *FixedSizeBinaryBuilder) Resize(n int) { + b.builder.resize(n, b.init) +} + +// NewArray creates a FixedSizeBinary array from the memory buffers used by the +// builder and resets the FixedSizeBinaryBuilder so it can be used to build a new array. +func (b *FixedSizeBinaryBuilder) NewArray() arrow.Array { + return b.NewFixedSizeBinaryArray() +} + +// NewFixedSizeBinaryArray creates a FixedSizeBinary array from the memory buffers used by the builder and resets the FixedSizeBinaryBuilder +// so it can be used to build a new array. +func (b *FixedSizeBinaryBuilder) NewFixedSizeBinaryArray() (a *FixedSizeBinary) { + data := b.newData() + a = NewFixedSizeBinaryData(data) + data.Release() + return +} + +func (b *FixedSizeBinaryBuilder) newData() (data *Data) { + values := b.values.Finish() + data = NewData(b.dtype, b.length, []*memory.Buffer{b.nullBitmap, values}, nil, b.nulls, 0) + + if values != nil { + values.Release() + } + + b.builder.reset() + + return +} + +func (b *FixedSizeBinaryBuilder) AppendValueFromString(s string) error { + if s == NullValueStr { + b.AppendNull() + return nil + } + + data, err := base64.StdEncoding.DecodeString(s) + if err != nil { + b.AppendNull() + return err + } + b.Append(data) + return nil +} + +func (b *FixedSizeBinaryBuilder) UnmarshalOne(dec *json.Decoder) error { + t, err := dec.Token() + if err != nil { + return err + } + + var val []byte + switch v := t.(type) { + case string: + data, err := base64.StdEncoding.DecodeString(v) + if err != nil { + return err + } + val = data + case []byte: + val = v + case nil: + b.AppendNull() + return nil + default: + return &json.UnmarshalTypeError{ + Value: fmt.Sprint(t), + Type: reflect.TypeOf([]byte{}), + Offset: dec.InputOffset(), + Struct: fmt.Sprintf("FixedSizeBinary[%d]", b.dtype.ByteWidth), + } + } + + if len(val) != b.dtype.ByteWidth { + return &json.UnmarshalTypeError{ + Value: fmt.Sprint(val), + Type: reflect.TypeOf([]byte{}), + Offset: dec.InputOffset(), + Struct: fmt.Sprintf("FixedSizeBinary[%d]", b.dtype.ByteWidth), + } + } + b.Append(val) + return nil +} + +func (b *FixedSizeBinaryBuilder) Unmarshal(dec *json.Decoder) error { + for dec.More() { + if err := b.UnmarshalOne(dec); err != nil { + return err + } + } + return nil +} + +func (b *FixedSizeBinaryBuilder) UnmarshalJSON(data []byte) error { + dec := json.NewDecoder(bytes.NewReader(data)) + t, err := dec.Token() + if err != nil { + return err + } + + if delim, ok := t.(json.Delim); !ok || delim != '[' { + return fmt.Errorf("fixed size binary builder must unpack from json array, found %s", delim) + } + + return b.Unmarshal(dec) +} + +var ( + _ Builder = (*FixedSizeBinaryBuilder)(nil) +) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array/float16.go b/vendor/github.com/apache/arrow/go/v14/arrow/array/float16.go new file mode 100644 index 000000000..de499e267 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array/float16.go @@ -0,0 +1,113 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package array + +import ( + "fmt" + "strings" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/float16" + "github.com/apache/arrow/go/v14/internal/json" +) + +// A type which represents an immutable sequence of Float16 values. +type Float16 struct { + array + values []float16.Num +} + +func NewFloat16Data(data arrow.ArrayData) *Float16 { + a := &Float16{} + a.refCount = 1 + a.setData(data.(*Data)) + return a +} + +func (a *Float16) Value(i int) float16.Num { return a.values[i] } +func (a *Float16) ValueStr(i int) string { + if a.IsNull(i) { + return NullValueStr + } + return a.Value(i).String() +} + +func (a *Float16) Values() []float16.Num { return a.values } + +func (a *Float16) String() string { + o := new(strings.Builder) + o.WriteString("[") + for i := 0; i < a.Len(); i++ { + if i > 0 { + fmt.Fprintf(o, " ") + } + switch { + case a.IsNull(i): + o.WriteString(NullValueStr) + default: + fmt.Fprintf(o, "%v", a.values[i].Float32()) + } + } + o.WriteString("]") + return o.String() +} + +func (a *Float16) setData(data *Data) { + a.array.setData(data) + vals := data.buffers[1] + if vals != nil { + a.values = arrow.Float16Traits.CastFromBytes(vals.Bytes()) + beg := a.array.data.offset + end := beg + a.array.data.length + a.values = a.values[beg:end] + } +} + +func (a *Float16) GetOneForMarshal(i int) interface{} { + if a.IsValid(i) { + return a.values[i].Float32() + } + return nil +} + +func (a *Float16) MarshalJSON() ([]byte, error) { + vals := make([]interface{}, a.Len()) + for i, v := range a.values { + if a.IsValid(i) { + vals[i] = v.Float32() + } else { + vals[i] = nil + } + } + return json.Marshal(vals) +} + +func arrayEqualFloat16(left, right *Float16) bool { + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + if left.Value(i) != right.Value(i) { + return false + } + } + return true +} + +var ( + _ arrow.Array = (*Float16)(nil) +) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array/float16_builder.go b/vendor/github.com/apache/arrow/go/v14/arrow/array/float16_builder.go new file mode 100644 index 000000000..f96ab6037 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array/float16_builder.go @@ -0,0 +1,263 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package array + +import ( + "bytes" + "fmt" + "reflect" + "strconv" + "sync/atomic" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/bitutil" + "github.com/apache/arrow/go/v14/arrow/float16" + "github.com/apache/arrow/go/v14/arrow/internal/debug" + "github.com/apache/arrow/go/v14/arrow/memory" + "github.com/apache/arrow/go/v14/internal/json" +) + +type Float16Builder struct { + builder + + data *memory.Buffer + rawData []float16.Num +} + +func NewFloat16Builder(mem memory.Allocator) *Float16Builder { + return &Float16Builder{builder: builder{refCount: 1, mem: mem}} +} + +func (b *Float16Builder) Type() arrow.DataType { return arrow.FixedWidthTypes.Float16 } + +// Release decreases the reference count by 1. +// When the reference count goes to zero, the memory is freed. +func (b *Float16Builder) Release() { + debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases") + + if atomic.AddInt64(&b.refCount, -1) == 0 { + if b.nullBitmap != nil { + b.nullBitmap.Release() + b.nullBitmap = nil + } + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + } +} + +func (b *Float16Builder) Append(v float16.Num) { + b.Reserve(1) + b.UnsafeAppend(v) +} + +func (b *Float16Builder) UnsafeAppend(v float16.Num) { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + b.rawData[b.length] = v + b.length++ +} + +func (b *Float16Builder) AppendNull() { + b.Reserve(1) + b.UnsafeAppendBoolToBitmap(false) +} + +func (b *Float16Builder) AppendNulls(n int) { + for i := 0; i < n; i++ { + b.AppendNull() + } +} + +func (b *Float16Builder) AppendEmptyValue() { + b.Reserve(1) + b.UnsafeAppend(float16.Num{}) +} + +func (b *Float16Builder) AppendEmptyValues(n int) { + for i := 0; i < n; i++ { + b.AppendEmptyValue() + } +} + +func (b *Float16Builder) UnsafeAppendBoolToBitmap(isValid bool) { + if isValid { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + } else { + b.nulls++ + } + b.length++ +} + +// AppendValues will append the values in the v slice. The valid slice determines which values +// in v are valid (not null). The valid slice must either be empty or be equal in length to v. If empty, +// all values in v are appended and considered valid. +func (b *Float16Builder) AppendValues(v []float16.Num, valid []bool) { + if len(v) != len(valid) && len(valid) != 0 { + panic("len(v) != len(valid) && len(valid) != 0") + } + + if len(v) == 0 { + return + } + + b.Reserve(len(v)) + if len(v) > 0 { + arrow.Float16Traits.Copy(b.rawData[b.length:], v) + } + b.builder.unsafeAppendBoolsToBitmap(valid, len(v)) +} + +func (b *Float16Builder) init(capacity int) { + b.builder.init(capacity) + + b.data = memory.NewResizableBuffer(b.mem) + bytesN := arrow.Uint16Traits.BytesRequired(capacity) + b.data.Resize(bytesN) + b.rawData = arrow.Float16Traits.CastFromBytes(b.data.Bytes()) +} + +// Reserve ensures there is enough space for appending n elements +// by checking the capacity and calling Resize if necessary. +func (b *Float16Builder) Reserve(n int) { + b.builder.reserve(n, b.Resize) +} + +// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(), +// additional memory will be allocated. If n is smaller, the allocated memory may reduced. +func (b *Float16Builder) Resize(n int) { + nBuilder := n + if n < minBuilderCapacity { + n = minBuilderCapacity + } + + if b.capacity == 0 { + b.init(n) + } else { + b.builder.resize(nBuilder, b.init) + b.data.Resize(arrow.Float16Traits.BytesRequired(n)) + b.rawData = arrow.Float16Traits.CastFromBytes(b.data.Bytes()) + } +} + +// NewArray creates a Float16 array from the memory buffers used by the builder and resets the Float16Builder +// so it can be used to build a new array. +func (b *Float16Builder) NewArray() arrow.Array { + return b.NewFloat16Array() +} + +// NewFloat16Array creates a Float16 array from the memory buffers used by the builder and resets the Float16Builder +// so it can be used to build a new array. +func (b *Float16Builder) NewFloat16Array() (a *Float16) { + data := b.newData() + a = NewFloat16Data(data) + data.Release() + return +} + +func (b *Float16Builder) newData() (data *Data) { + bytesRequired := arrow.Float16Traits.BytesRequired(b.length) + if bytesRequired > 0 && bytesRequired < b.data.Len() { + // trim buffers + b.data.Resize(bytesRequired) + } + data = NewData(arrow.FixedWidthTypes.Float16, b.length, []*memory.Buffer{b.nullBitmap, b.data}, nil, b.nulls, 0) + b.reset() + + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + + return +} + +func (b *Float16Builder) AppendValueFromString(s string) error { + if s == NullValueStr { + b.AppendNull() + return nil + } + v, err := strconv.ParseFloat(s, 32) + if err != nil { + b.AppendNull() + return err + } + b.Append(float16.New(float32(v))) + return nil +} + +func (b *Float16Builder) UnmarshalOne(dec *json.Decoder) error { + t, err := dec.Token() + if err != nil { + return err + } + + switch v := t.(type) { + case float64: + b.Append(float16.New(float32(v))) + case string: + f, err := strconv.ParseFloat(v, 32) + if err != nil { + return err + } + // this will currently silently truncate if it is too large + b.Append(float16.New(float32(f))) + case json.Number: + f, err := v.Float64() + if err != nil { + return err + } + b.Append(float16.New(float32(f))) + case nil: + b.AppendNull() + default: + return &json.UnmarshalTypeError{ + Value: fmt.Sprint(t), + Type: reflect.TypeOf(float16.Num{}), + Offset: dec.InputOffset(), + } + } + return nil +} + +func (b *Float16Builder) Unmarshal(dec *json.Decoder) error { + for dec.More() { + if err := b.UnmarshalOne(dec); err != nil { + return err + } + } + return nil +} + +// UnmarshalJSON will add values to this builder from unmarshalling the +// array of values. Currently values that are larger than a float16 will +// be silently truncated. +func (b *Float16Builder) UnmarshalJSON(data []byte) error { + dec := json.NewDecoder(bytes.NewReader(data)) + t, err := dec.Token() + if err != nil { + return err + } + + if delim, ok := t.(json.Delim); !ok || delim != '[' { + return fmt.Errorf("float16 builder must unpack from json array, found %s", delim) + } + + return b.Unmarshal(dec) +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array/interval.go b/vendor/github.com/apache/arrow/go/v14/arrow/array/interval.go new file mode 100644 index 000000000..ff059c92c --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array/interval.go @@ -0,0 +1,953 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package array + +import ( + "bytes" + "fmt" + "strconv" + "strings" + "sync/atomic" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/bitutil" + "github.com/apache/arrow/go/v14/arrow/internal/debug" + "github.com/apache/arrow/go/v14/arrow/memory" + "github.com/apache/arrow/go/v14/internal/json" +) + +func NewIntervalData(data arrow.ArrayData) arrow.Array { + switch data.DataType().(type) { + case *arrow.MonthIntervalType: + return NewMonthIntervalData(data.(*Data)) + case *arrow.DayTimeIntervalType: + return NewDayTimeIntervalData(data.(*Data)) + case *arrow.MonthDayNanoIntervalType: + return NewMonthDayNanoIntervalData(data.(*Data)) + default: + panic(fmt.Errorf("arrow/array: unknown interval data type %T", data.DataType())) + } +} + +// A type which represents an immutable sequence of arrow.MonthInterval values. +type MonthInterval struct { + array + values []arrow.MonthInterval +} + +func NewMonthIntervalData(data arrow.ArrayData) *MonthInterval { + a := &MonthInterval{} + a.refCount = 1 + a.setData(data.(*Data)) + return a +} + +func (a *MonthInterval) Value(i int) arrow.MonthInterval { return a.values[i] } +func (a *MonthInterval) ValueStr(i int) string { + if a.IsNull(i) { + return NullValueStr + } + return fmt.Sprintf("%v", a.Value(i)) +} +func (a *MonthInterval) MonthIntervalValues() []arrow.MonthInterval { return a.values } + +func (a *MonthInterval) String() string { + o := new(strings.Builder) + o.WriteString("[") + for i, v := range a.values { + if i > 0 { + fmt.Fprintf(o, " ") + } + switch { + case a.IsNull(i): + o.WriteString(NullValueStr) + default: + fmt.Fprintf(o, "%v", v) + } + } + o.WriteString("]") + return o.String() +} + +func (a *MonthInterval) setData(data *Data) { + a.array.setData(data) + vals := data.buffers[1] + if vals != nil { + a.values = arrow.MonthIntervalTraits.CastFromBytes(vals.Bytes()) + beg := a.array.data.offset + end := beg + a.array.data.length + a.values = a.values[beg:end] + } +} + +func (a *MonthInterval) GetOneForMarshal(i int) interface{} { + if a.IsValid(i) { + return a.values[i] + } + return nil +} + +// MarshalJSON will create a json array out of a MonthInterval array, +// each value will be an object of the form {"months": #} where +// # is the numeric value of that index +func (a *MonthInterval) MarshalJSON() ([]byte, error) { + if a.NullN() == 0 { + return json.Marshal(a.values) + } + vals := make([]interface{}, a.Len()) + for i := 0; i < a.Len(); i++ { + if a.IsValid(i) { + vals[i] = a.values[i] + } else { + vals[i] = nil + } + } + + return json.Marshal(vals) +} + +func arrayEqualMonthInterval(left, right *MonthInterval) bool { + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + if left.Value(i) != right.Value(i) { + return false + } + } + return true +} + +type MonthIntervalBuilder struct { + builder + + data *memory.Buffer + rawData []arrow.MonthInterval +} + +func NewMonthIntervalBuilder(mem memory.Allocator) *MonthIntervalBuilder { + return &MonthIntervalBuilder{builder: builder{refCount: 1, mem: mem}} +} + +func (b *MonthIntervalBuilder) Type() arrow.DataType { return arrow.FixedWidthTypes.MonthInterval } + +// Release decreases the reference count by 1. +// When the reference count goes to zero, the memory is freed. +func (b *MonthIntervalBuilder) Release() { + debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases") + + if atomic.AddInt64(&b.refCount, -1) == 0 { + if b.nullBitmap != nil { + b.nullBitmap.Release() + b.nullBitmap = nil + } + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + } +} + +func (b *MonthIntervalBuilder) Append(v arrow.MonthInterval) { + b.Reserve(1) + b.UnsafeAppend(v) +} + +func (b *MonthIntervalBuilder) AppendNull() { + b.Reserve(1) + b.UnsafeAppendBoolToBitmap(false) +} + +func (b *MonthIntervalBuilder) AppendNulls(n int) { + for i := 0; i < n; i++ { + b.AppendNull() + } +} + +func (b *MonthIntervalBuilder) AppendEmptyValue() { + b.Append(arrow.MonthInterval(0)) +} + +func (b *MonthIntervalBuilder) AppendEmptyValues(n int) { + for i := 0; i < n; i++ { + b.AppendEmptyValue() + } +} + +func (b *MonthIntervalBuilder) UnsafeAppend(v arrow.MonthInterval) { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + b.rawData[b.length] = v + b.length++ +} + +func (b *MonthIntervalBuilder) UnsafeAppendBoolToBitmap(isValid bool) { + if isValid { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + } else { + b.nulls++ + } + b.length++ +} + +// AppendValues will append the values in the v slice. The valid slice determines which values +// in v are valid (not null). The valid slice must either be empty or be equal in length to v. If empty, +// all values in v are appended and considered valid. +func (b *MonthIntervalBuilder) AppendValues(v []arrow.MonthInterval, valid []bool) { + if len(v) != len(valid) && len(valid) != 0 { + panic("len(v) != len(valid) && len(valid) != 0") + } + + if len(v) == 0 { + return + } + + b.Reserve(len(v)) + arrow.MonthIntervalTraits.Copy(b.rawData[b.length:], v) + b.builder.unsafeAppendBoolsToBitmap(valid, len(v)) +} + +func (b *MonthIntervalBuilder) init(capacity int) { + b.builder.init(capacity) + + b.data = memory.NewResizableBuffer(b.mem) + bytesN := arrow.MonthIntervalTraits.BytesRequired(capacity) + b.data.Resize(bytesN) + b.rawData = arrow.MonthIntervalTraits.CastFromBytes(b.data.Bytes()) +} + +// Reserve ensures there is enough space for appending n elements +// by checking the capacity and calling Resize if necessary. +func (b *MonthIntervalBuilder) Reserve(n int) { + b.builder.reserve(n, b.Resize) +} + +// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(), +// additional memory will be allocated. If n is smaller, the allocated memory may reduced. +func (b *MonthIntervalBuilder) Resize(n int) { + nBuilder := n + if n < minBuilderCapacity { + n = minBuilderCapacity + } + + if b.capacity == 0 { + b.init(n) + } else { + b.builder.resize(nBuilder, b.init) + b.data.Resize(arrow.MonthIntervalTraits.BytesRequired(n)) + b.rawData = arrow.MonthIntervalTraits.CastFromBytes(b.data.Bytes()) + } +} + +// NewArray creates a MonthInterval array from the memory buffers used by the builder and resets the MonthIntervalBuilder +// so it can be used to build a new array. +func (b *MonthIntervalBuilder) NewArray() arrow.Array { + return b.NewMonthIntervalArray() +} + +// NewMonthIntervalArray creates a MonthInterval array from the memory buffers used by the builder and resets the MonthIntervalBuilder +// so it can be used to build a new array. +func (b *MonthIntervalBuilder) NewMonthIntervalArray() (a *MonthInterval) { + data := b.newData() + a = NewMonthIntervalData(data) + data.Release() + return +} + +func (b *MonthIntervalBuilder) newData() (data *Data) { + bytesRequired := arrow.MonthIntervalTraits.BytesRequired(b.length) + if bytesRequired > 0 && bytesRequired < b.data.Len() { + // trim buffers + b.data.Resize(bytesRequired) + } + data = NewData(arrow.FixedWidthTypes.MonthInterval, b.length, []*memory.Buffer{b.nullBitmap, b.data}, nil, b.nulls, 0) + b.reset() + + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + + return +} + +func (b *MonthIntervalBuilder) AppendValueFromString(s string) error { + if s == NullValueStr { + b.AppendNull() + return nil + } + v, err := strconv.ParseInt(s, 10, 32) + if err != nil { + b.AppendNull() + return err + } + b.Append(arrow.MonthInterval(v)) + return nil +} + +func (b *MonthIntervalBuilder) UnmarshalOne(dec *json.Decoder) error { + var v *arrow.MonthInterval + if err := dec.Decode(&v); err != nil { + return err + } + + if v == nil { + b.AppendNull() + } else { + b.Append(*v) + } + return nil +} + +func (b *MonthIntervalBuilder) Unmarshal(dec *json.Decoder) error { + for dec.More() { + if err := b.UnmarshalOne(dec); err != nil { + return err + } + } + return nil +} + +// UnmarshalJSON will add the unmarshalled values of an array to the builder, +// values are expected to be strings of the form "#months" where # is the int32 +// value that will be added to the builder. +func (b *MonthIntervalBuilder) UnmarshalJSON(data []byte) error { + dec := json.NewDecoder(bytes.NewReader(data)) + t, err := dec.Token() + if err != nil { + return err + } + + if delim, ok := t.(json.Delim); !ok || delim != '[' { + return fmt.Errorf("month interval builder must unpack from json array, found %s", delim) + } + + return b.Unmarshal(dec) +} + +// A type which represents an immutable sequence of arrow.DayTimeInterval values. +type DayTimeInterval struct { + array + values []arrow.DayTimeInterval +} + +func NewDayTimeIntervalData(data arrow.ArrayData) *DayTimeInterval { + a := &DayTimeInterval{} + a.refCount = 1 + a.setData(data.(*Data)) + return a +} + +func (a *DayTimeInterval) Value(i int) arrow.DayTimeInterval { return a.values[i] } +func (a *DayTimeInterval) ValueStr(i int) string { + if a.IsNull(i) { + return NullValueStr + } + data, err := json.Marshal(a.GetOneForMarshal(i)) + if err != nil { + panic(err) + } + return string(data) +} + +func (a *DayTimeInterval) DayTimeIntervalValues() []arrow.DayTimeInterval { return a.values } + +func (a *DayTimeInterval) String() string { + o := new(strings.Builder) + o.WriteString("[") + for i, v := range a.values { + if i > 0 { + fmt.Fprintf(o, " ") + } + switch { + case a.IsNull(i): + o.WriteString(NullValueStr) + default: + fmt.Fprintf(o, "%v", v) + } + } + o.WriteString("]") + return o.String() +} + +func (a *DayTimeInterval) setData(data *Data) { + a.array.setData(data) + vals := data.buffers[1] + if vals != nil { + a.values = arrow.DayTimeIntervalTraits.CastFromBytes(vals.Bytes()) + beg := a.array.data.offset + end := beg + a.array.data.length + a.values = a.values[beg:end] + } +} + +func (a *DayTimeInterval) GetOneForMarshal(i int) interface{} { + if a.IsValid(i) { + return a.values[i] + } + return nil +} + +// MarshalJSON will marshal this array to JSON as an array of objects, +// consisting of the form {"days": #, "milliseconds": #} for each element. +func (a *DayTimeInterval) MarshalJSON() ([]byte, error) { + if a.NullN() == 0 { + return json.Marshal(a.values) + } + vals := make([]interface{}, a.Len()) + for i, v := range a.values { + if a.IsValid(i) { + vals[i] = v + } else { + vals[i] = nil + } + } + return json.Marshal(vals) +} + +func arrayEqualDayTimeInterval(left, right *DayTimeInterval) bool { + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + if left.Value(i) != right.Value(i) { + return false + } + } + return true +} + +type DayTimeIntervalBuilder struct { + builder + + data *memory.Buffer + rawData []arrow.DayTimeInterval +} + +func NewDayTimeIntervalBuilder(mem memory.Allocator) *DayTimeIntervalBuilder { + return &DayTimeIntervalBuilder{builder: builder{refCount: 1, mem: mem}} +} + +func (b *DayTimeIntervalBuilder) Type() arrow.DataType { return arrow.FixedWidthTypes.DayTimeInterval } + +// Release decreases the reference count by 1. +// When the reference count goes to zero, the memory is freed. +func (b *DayTimeIntervalBuilder) Release() { + debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases") + + if atomic.AddInt64(&b.refCount, -1) == 0 { + if b.nullBitmap != nil { + b.nullBitmap.Release() + b.nullBitmap = nil + } + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + } +} + +func (b *DayTimeIntervalBuilder) Append(v arrow.DayTimeInterval) { + b.Reserve(1) + b.UnsafeAppend(v) +} + +func (b *DayTimeIntervalBuilder) AppendNull() { + b.Reserve(1) + b.UnsafeAppendBoolToBitmap(false) +} + +func (b *DayTimeIntervalBuilder) AppendNulls(n int) { + for i := 0; i < n; i++ { + b.AppendNull() + } +} + +func (b *DayTimeIntervalBuilder) AppendEmptyValue() { + b.Append(arrow.DayTimeInterval{}) +} + +func (b *DayTimeIntervalBuilder) AppendEmptyValues(n int) { + for i := 0; i < n; i++ { + b.AppendEmptyValue() + } +} + +func (b *DayTimeIntervalBuilder) UnsafeAppend(v arrow.DayTimeInterval) { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + b.rawData[b.length] = v + b.length++ +} + +func (b *DayTimeIntervalBuilder) UnsafeAppendBoolToBitmap(isValid bool) { + if isValid { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + } else { + b.nulls++ + } + b.length++ +} + +// AppendValues will append the values in the v slice. The valid slice determines which values +// in v are valid (not null). The valid slice must either be empty or be equal in length to v. If empty, +// all values in v are appended and considered valid. +func (b *DayTimeIntervalBuilder) AppendValues(v []arrow.DayTimeInterval, valid []bool) { + if len(v) != len(valid) && len(valid) != 0 { + panic("len(v) != len(valid) && len(valid) != 0") + } + + if len(v) == 0 { + return + } + + b.Reserve(len(v)) + arrow.DayTimeIntervalTraits.Copy(b.rawData[b.length:], v) + b.builder.unsafeAppendBoolsToBitmap(valid, len(v)) +} + +func (b *DayTimeIntervalBuilder) init(capacity int) { + b.builder.init(capacity) + + b.data = memory.NewResizableBuffer(b.mem) + bytesN := arrow.DayTimeIntervalTraits.BytesRequired(capacity) + b.data.Resize(bytesN) + b.rawData = arrow.DayTimeIntervalTraits.CastFromBytes(b.data.Bytes()) +} + +// Reserve ensures there is enough space for appending n elements +// by checking the capacity and calling Resize if necessary. +func (b *DayTimeIntervalBuilder) Reserve(n int) { + b.builder.reserve(n, b.Resize) +} + +// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(), +// additional memory will be allocated. If n is smaller, the allocated memory may reduced. +func (b *DayTimeIntervalBuilder) Resize(n int) { + nBuilder := n + if n < minBuilderCapacity { + n = minBuilderCapacity + } + + if b.capacity == 0 { + b.init(n) + } else { + b.builder.resize(nBuilder, b.init) + b.data.Resize(arrow.DayTimeIntervalTraits.BytesRequired(n)) + b.rawData = arrow.DayTimeIntervalTraits.CastFromBytes(b.data.Bytes()) + } +} + +// NewArray creates a DayTimeInterval array from the memory buffers used by the builder and resets the DayTimeIntervalBuilder +// so it can be used to build a new array. +func (b *DayTimeIntervalBuilder) NewArray() arrow.Array { + return b.NewDayTimeIntervalArray() +} + +// NewDayTimeIntervalArray creates a DayTimeInterval array from the memory buffers used by the builder and resets the DayTimeIntervalBuilder +// so it can be used to build a new array. +func (b *DayTimeIntervalBuilder) NewDayTimeIntervalArray() (a *DayTimeInterval) { + data := b.newData() + a = NewDayTimeIntervalData(data) + data.Release() + return +} + +func (b *DayTimeIntervalBuilder) newData() (data *Data) { + bytesRequired := arrow.DayTimeIntervalTraits.BytesRequired(b.length) + if bytesRequired > 0 && bytesRequired < b.data.Len() { + // trim buffers + b.data.Resize(bytesRequired) + } + data = NewData(arrow.FixedWidthTypes.DayTimeInterval, b.length, []*memory.Buffer{b.nullBitmap, b.data}, nil, b.nulls, 0) + b.reset() + + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + + return +} + +func (b *DayTimeIntervalBuilder) AppendValueFromString(s string) error { + if s == NullValueStr { + b.AppendNull() + return nil + } + var v arrow.DayTimeInterval + if err := json.Unmarshal([]byte(s), &v); err != nil { + b.AppendNull() + return err + } + b.Append(v) + return nil +} + +func (b *DayTimeIntervalBuilder) UnmarshalOne(dec *json.Decoder) error { + var v *arrow.DayTimeInterval + if err := dec.Decode(&v); err != nil { + return err + } + + if v == nil { + b.AppendNull() + } else { + b.Append(*v) + } + return nil +} + +func (b *DayTimeIntervalBuilder) Unmarshal(dec *json.Decoder) error { + for dec.More() { + if err := b.UnmarshalOne(dec); err != nil { + return err + } + } + return nil +} + +// UnmarshalJSON will add the values unmarshalled from an array to the builder, +// with the values expected to be objects of the form {"days": #, "milliseconds": #} +func (b *DayTimeIntervalBuilder) UnmarshalJSON(data []byte) error { + dec := json.NewDecoder(bytes.NewReader(data)) + t, err := dec.Token() + if err != nil { + return err + } + + if delim, ok := t.(json.Delim); !ok || delim != '[' { + return fmt.Errorf("day_time interval builder must unpack from json array, found %s", delim) + } + + return b.Unmarshal(dec) +} + +// A type which represents an immutable sequence of arrow.DayTimeInterval values. +type MonthDayNanoInterval struct { + array + values []arrow.MonthDayNanoInterval +} + +func NewMonthDayNanoIntervalData(data arrow.ArrayData) *MonthDayNanoInterval { + a := &MonthDayNanoInterval{} + a.refCount = 1 + a.setData(data.(*Data)) + return a +} + +func (a *MonthDayNanoInterval) Value(i int) arrow.MonthDayNanoInterval { return a.values[i] } +func (a *MonthDayNanoInterval) ValueStr(i int) string { + if a.IsNull(i) { + return NullValueStr + } + data, err := json.Marshal(a.GetOneForMarshal(i)) + if err != nil { + panic(err) + } + return string(data) +} + +func (a *MonthDayNanoInterval) MonthDayNanoIntervalValues() []arrow.MonthDayNanoInterval { + return a.values +} + +func (a *MonthDayNanoInterval) String() string { + o := new(strings.Builder) + o.WriteString("[") + for i, v := range a.values { + if i > 0 { + fmt.Fprintf(o, " ") + } + switch { + case a.IsNull(i): + o.WriteString(NullValueStr) + default: + fmt.Fprintf(o, "%v", v) + } + } + o.WriteString("]") + return o.String() +} + +func (a *MonthDayNanoInterval) setData(data *Data) { + a.array.setData(data) + vals := data.buffers[1] + if vals != nil { + a.values = arrow.MonthDayNanoIntervalTraits.CastFromBytes(vals.Bytes()) + beg := a.array.data.offset + end := beg + a.array.data.length + a.values = a.values[beg:end] + } +} + +func (a *MonthDayNanoInterval) GetOneForMarshal(i int) interface{} { + if a.IsValid(i) { + return a.values[i] + } + return nil +} + +// MarshalJSON will marshal this array to a JSON array with elements +// marshalled to the form {"months": #, "days": #, "nanoseconds": #} +func (a *MonthDayNanoInterval) MarshalJSON() ([]byte, error) { + if a.NullN() == 0 { + return json.Marshal(a.values) + } + vals := make([]interface{}, a.Len()) + for i, v := range a.values { + if a.IsValid(i) { + vals[i] = v + } else { + vals[i] = nil + } + } + return json.Marshal(vals) +} + +func arrayEqualMonthDayNanoInterval(left, right *MonthDayNanoInterval) bool { + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + if left.Value(i) != right.Value(i) { + return false + } + } + return true +} + +type MonthDayNanoIntervalBuilder struct { + builder + + data *memory.Buffer + rawData []arrow.MonthDayNanoInterval +} + +func NewMonthDayNanoIntervalBuilder(mem memory.Allocator) *MonthDayNanoIntervalBuilder { + return &MonthDayNanoIntervalBuilder{builder: builder{refCount: 1, mem: mem}} +} + +func (b *MonthDayNanoIntervalBuilder) Type() arrow.DataType { + return arrow.FixedWidthTypes.MonthDayNanoInterval +} + +// Release decreases the reference count by 1. +// When the reference count goes to zero, the memory is freed. +func (b *MonthDayNanoIntervalBuilder) Release() { + debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases") + + if atomic.AddInt64(&b.refCount, -1) == 0 { + if b.nullBitmap != nil { + b.nullBitmap.Release() + b.nullBitmap = nil + } + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + } +} + +func (b *MonthDayNanoIntervalBuilder) Append(v arrow.MonthDayNanoInterval) { + b.Reserve(1) + b.UnsafeAppend(v) +} + +func (b *MonthDayNanoIntervalBuilder) AppendNull() { + b.Reserve(1) + b.UnsafeAppendBoolToBitmap(false) +} + +func (b *MonthDayNanoIntervalBuilder) AppendNulls(n int) { + for i := 0; i < n; i++ { + b.AppendNull() + } +} + +func (b *MonthDayNanoIntervalBuilder) AppendEmptyValue() { + b.Append(arrow.MonthDayNanoInterval{}) +} + +func (b *MonthDayNanoIntervalBuilder) AppendEmptyValues(n int) { + for i := 0; i < n; i++ { + b.AppendEmptyValue() + } +} + +func (b *MonthDayNanoIntervalBuilder) UnsafeAppend(v arrow.MonthDayNanoInterval) { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + b.rawData[b.length] = v + b.length++ +} + +func (b *MonthDayNanoIntervalBuilder) UnsafeAppendBoolToBitmap(isValid bool) { + if isValid { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + } else { + b.nulls++ + } + b.length++ +} + +// AppendValues will append the values in the v slice. The valid slice determines which values +// in v are valid (not null). The valid slice must either be empty or be equal in length to v. If empty, +// all values in v are appended and considered valid. +func (b *MonthDayNanoIntervalBuilder) AppendValues(v []arrow.MonthDayNanoInterval, valid []bool) { + if len(v) != len(valid) && len(valid) != 0 { + panic("len(v) != len(valid) && len(valid) != 0") + } + + if len(v) == 0 { + return + } + + b.Reserve(len(v)) + arrow.MonthDayNanoIntervalTraits.Copy(b.rawData[b.length:], v) + b.builder.unsafeAppendBoolsToBitmap(valid, len(v)) +} + +func (b *MonthDayNanoIntervalBuilder) init(capacity int) { + b.builder.init(capacity) + + b.data = memory.NewResizableBuffer(b.mem) + bytesN := arrow.MonthDayNanoIntervalTraits.BytesRequired(capacity) + b.data.Resize(bytesN) + b.rawData = arrow.MonthDayNanoIntervalTraits.CastFromBytes(b.data.Bytes()) +} + +// Reserve ensures there is enough space for appending n elements +// by checking the capacity and calling Resize if necessary. +func (b *MonthDayNanoIntervalBuilder) Reserve(n int) { + b.builder.reserve(n, b.Resize) +} + +// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(), +// additional memory will be allocated. If n is smaller, the allocated memory may reduced. +func (b *MonthDayNanoIntervalBuilder) Resize(n int) { + nBuilder := n + if n < minBuilderCapacity { + n = minBuilderCapacity + } + + if b.capacity == 0 { + b.init(n) + } else { + b.builder.resize(nBuilder, b.init) + b.data.Resize(arrow.MonthDayNanoIntervalTraits.BytesRequired(n)) + b.rawData = arrow.MonthDayNanoIntervalTraits.CastFromBytes(b.data.Bytes()) + } +} + +// NewArray creates a MonthDayNanoInterval array from the memory buffers used by the builder and resets the MonthDayNanoIntervalBuilder +// so it can be used to build a new array. +func (b *MonthDayNanoIntervalBuilder) NewArray() arrow.Array { + return b.NewMonthDayNanoIntervalArray() +} + +// NewMonthDayNanoIntervalArray creates a MonthDayNanoInterval array from the memory buffers used by the builder and resets the MonthDayNanoIntervalBuilder +// so it can be used to build a new array. +func (b *MonthDayNanoIntervalBuilder) NewMonthDayNanoIntervalArray() (a *MonthDayNanoInterval) { + data := b.newData() + a = NewMonthDayNanoIntervalData(data) + data.Release() + return +} + +func (b *MonthDayNanoIntervalBuilder) newData() (data *Data) { + bytesRequired := arrow.MonthDayNanoIntervalTraits.BytesRequired(b.length) + if bytesRequired > 0 && bytesRequired < b.data.Len() { + // trim buffers + b.data.Resize(bytesRequired) + } + data = NewData(arrow.FixedWidthTypes.MonthDayNanoInterval, b.length, []*memory.Buffer{b.nullBitmap, b.data}, nil, b.nulls, 0) + b.reset() + + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + + return +} + +func (b *MonthDayNanoIntervalBuilder) AppendValueFromString(s string) error { + if s == NullValueStr { + b.AppendNull() + return nil + } + var v arrow.MonthDayNanoInterval + if err := json.Unmarshal([]byte(s), &v); err != nil { + return err + } + b.Append(v) + return nil +} + +func (b *MonthDayNanoIntervalBuilder) UnmarshalOne(dec *json.Decoder) error { + var v *arrow.MonthDayNanoInterval + if err := dec.Decode(&v); err != nil { + return err + } + + if v == nil { + b.AppendNull() + } else { + b.Append(*v) + } + return nil +} + +func (b *MonthDayNanoIntervalBuilder) Unmarshal(dec *json.Decoder) error { + for dec.More() { + if err := b.UnmarshalOne(dec); err != nil { + return err + } + } + return nil +} + +// UnmarshalJSON unmarshals a JSON array of objects and adds them to this builder, +// each element of the array is expected to be an object of the form +// {"months": #, "days": #, "nanoseconds": #} +func (b *MonthDayNanoIntervalBuilder) UnmarshalJSON(data []byte) error { + dec := json.NewDecoder(bytes.NewReader(data)) + t, err := dec.Token() + if err != nil { + return err + } + + if delim, ok := t.(json.Delim); !ok || delim != '[' { + return fmt.Errorf("month_day_nano interval builder must unpack from json array, found %s", delim) + } + + return b.Unmarshal(dec) +} + +var ( + _ arrow.Array = (*MonthInterval)(nil) + _ arrow.Array = (*DayTimeInterval)(nil) + _ arrow.Array = (*MonthDayNanoInterval)(nil) + + _ Builder = (*MonthIntervalBuilder)(nil) + _ Builder = (*DayTimeIntervalBuilder)(nil) + _ Builder = (*MonthDayNanoIntervalBuilder)(nil) +) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array/json_reader.go b/vendor/github.com/apache/arrow/go/v14/arrow/array/json_reader.go new file mode 100644 index 000000000..e09717c41 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array/json_reader.go @@ -0,0 +1,205 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package array + +import ( + "errors" + "fmt" + "io" + "sync/atomic" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/internal/debug" + "github.com/apache/arrow/go/v14/arrow/memory" + "github.com/apache/arrow/go/v14/internal/json" +) + +type Option func(config) +type config interface{} + +// WithChunk sets the chunk size for reading in json records. The default is to +// read in one row per record batch as a single object. If chunk size is set to +// a negative value, then the entire file is read as a single record batch. +// Otherwise a record batch is read in with chunk size rows per record batch until +// it reaches EOF. +func WithChunk(n int) Option { + return func(cfg config) { + switch cfg := cfg.(type) { + case *JSONReader: + cfg.chunk = n + default: + panic(fmt.Errorf("arrow/json): unknown config type %T", cfg)) + } + } +} + +// WithAllocator specifies the allocator to use for creating the record batches, +// if it is not called, then memory.DefaultAllocator will be used. +func WithAllocator(mem memory.Allocator) Option { + return func(cfg config) { + switch cfg := cfg.(type) { + case *JSONReader: + cfg.mem = mem + default: + panic(fmt.Errorf("arrow/json): unknown config type %T", cfg)) + } + } +} + +// JSONReader is a json reader that meets the RecordReader interface definition. +// +// To read in an array of objects as a record, you can use RecordFromJSON +// which is equivalent to reading the json as a struct array whose fields are +// the columns of the record. This primarily exists to fit the RecordReader +// interface as a matching reader for the csv reader. +type JSONReader struct { + r *json.Decoder + schema *arrow.Schema + + bldr *RecordBuilder + + refs int64 + cur arrow.Record + err error + + chunk int + done bool + + mem memory.Allocator + next func() bool +} + +// NewJSONReader returns a json RecordReader which expects to find one json object +// per row of dataset. Using WithChunk can control how many rows are processed +// per record, which is how many objects become a single record from the file. +// +// If it is desired to write out an array of rows, then simply use RecordToStructArray +// and json.Marshal the struct array for the same effect. +func NewJSONReader(r io.Reader, schema *arrow.Schema, opts ...Option) *JSONReader { + rr := &JSONReader{ + r: json.NewDecoder(r), + schema: schema, + refs: 1, + chunk: 1, + } + for _, o := range opts { + o(rr) + } + + if rr.mem == nil { + rr.mem = memory.DefaultAllocator + } + + rr.bldr = NewRecordBuilder(rr.mem, schema) + switch { + case rr.chunk < 0: + rr.next = rr.nextall + case rr.chunk > 1: + rr.next = rr.nextn + default: + rr.next = rr.next1 + } + return rr +} + +// Err returns the last encountered error +func (r *JSONReader) Err() error { return r.err } + +func (r *JSONReader) Schema() *arrow.Schema { return r.schema } + +// Record returns the last read in record. The returned record is only valid +// until the next call to Next unless Retain is called on the record itself. +func (r *JSONReader) Record() arrow.Record { return r.cur } + +func (r *JSONReader) Retain() { + atomic.AddInt64(&r.refs, 1) +} + +func (r *JSONReader) Release() { + debug.Assert(atomic.LoadInt64(&r.refs) > 0, "too many releases") + + if atomic.AddInt64(&r.refs, -1) == 0 { + if r.cur != nil { + r.cur.Release() + r.bldr.Release() + r.r = nil + } + } +} + +// Next returns true if it read in a record, which will be available via Record +// and false if there is either an error or the end of the reader. +func (r *JSONReader) Next() bool { + if r.cur != nil { + r.cur.Release() + r.cur = nil + } + + if r.err != nil || r.done { + return false + } + + return r.next() +} + +func (r *JSONReader) readNext() bool { + r.err = r.r.Decode(r.bldr) + if r.err != nil { + r.done = true + if errors.Is(r.err, io.EOF) { + r.err = nil + } + return false + } + return true +} + +func (r *JSONReader) nextall() bool { + for r.readNext() { + } + + r.cur = r.bldr.NewRecord() + return r.cur.NumRows() > 0 +} + +func (r *JSONReader) next1() bool { + if !r.readNext() { + return false + } + + r.cur = r.bldr.NewRecord() + return true +} + +func (r *JSONReader) nextn() bool { + var n = 0 + + for i := 0; i < r.chunk && !r.done; i, n = i+1, n+1 { + if !r.readNext() { + break + } + } + + if n > 0 { + r.cur = r.bldr.NewRecord() + } + return n > 0 +} + +var ( + _ RecordReader = (*JSONReader)(nil) +) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array/list.go b/vendor/github.com/apache/arrow/go/v14/arrow/array/list.go new file mode 100644 index 000000000..d8d8b8c76 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array/list.go @@ -0,0 +1,1688 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package array + +import ( + "bytes" + "fmt" + "math" + "strings" + "sync/atomic" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/bitutil" + "github.com/apache/arrow/go/v14/arrow/internal/debug" + "github.com/apache/arrow/go/v14/arrow/memory" + "github.com/apache/arrow/go/v14/internal/json" +) + +type ListLike interface { + arrow.Array + ListValues() arrow.Array + ValueOffsets(i int) (start, end int64) +} + +type VarLenListLike interface { + ListLike +} + +// List represents an immutable sequence of array values. +type List struct { + array + values arrow.Array + offsets []int32 +} + +var _ ListLike = (*List)(nil) + +// NewListData returns a new List array value, from data. +func NewListData(data arrow.ArrayData) *List { + a := &List{} + a.refCount = 1 + a.setData(data.(*Data)) + return a +} + +func (a *List) ListValues() arrow.Array { return a.values } + +func (a *List) ValueStr(i int) string { + if !a.IsValid(i) { + return NullValueStr + } + return string(a.GetOneForMarshal(i).(json.RawMessage)) +} + +func (a *List) String() string { + o := new(strings.Builder) + o.WriteString("[") + for i := 0; i < a.Len(); i++ { + if i > 0 { + o.WriteString(" ") + } + if a.IsNull(i) { + o.WriteString(NullValueStr) + continue + } + sub := a.newListValue(i) + fmt.Fprintf(o, "%v", sub) + sub.Release() + } + o.WriteString("]") + return o.String() +} + +func (a *List) newListValue(i int) arrow.Array { + beg, end := a.ValueOffsets(i) + return NewSlice(a.values, beg, end) +} + +func (a *List) setData(data *Data) { + debug.Assert(len(data.buffers) >= 2, "list data should have 2 buffers") + a.array.setData(data) + vals := data.buffers[1] + if vals != nil { + a.offsets = arrow.Int32Traits.CastFromBytes(vals.Bytes()) + } + a.values = MakeFromData(data.childData[0]) +} + +func (a *List) GetOneForMarshal(i int) interface{} { + if a.IsNull(i) { + return nil + } + + slice := a.newListValue(i) + defer slice.Release() + v, err := json.Marshal(slice) + if err != nil { + panic(err) + } + return json.RawMessage(v) +} + +func (a *List) MarshalJSON() ([]byte, error) { + var buf bytes.Buffer + enc := json.NewEncoder(&buf) + + buf.WriteByte('[') + for i := 0; i < a.Len(); i++ { + if i != 0 { + buf.WriteByte(',') + } + if err := enc.Encode(a.GetOneForMarshal(i)); err != nil { + return nil, err + } + } + buf.WriteByte(']') + return buf.Bytes(), nil +} + +func arrayEqualList(left, right *List) bool { + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + o := func() bool { + l := left.newListValue(i) + defer l.Release() + r := right.newListValue(i) + defer r.Release() + return Equal(l, r) + }() + if !o { + return false + } + } + return true +} + +// Len returns the number of elements in the array. +func (a *List) Len() int { return a.array.Len() } + +func (a *List) Offsets() []int32 { return a.offsets } + +func (a *List) Retain() { + a.array.Retain() + a.values.Retain() +} + +func (a *List) Release() { + a.array.Release() + a.values.Release() +} + +func (a *List) ValueOffsets(i int) (start, end int64) { + debug.Assert(i >= 0 && i < a.array.data.length, "index out of range") + j := i + a.array.data.offset + start, end = int64(a.offsets[j]), int64(a.offsets[j+1]) + return +} + +// LargeList represents an immutable sequence of array values. +type LargeList struct { + array + values arrow.Array + offsets []int64 +} + +var _ ListLike = (*LargeList)(nil) + +// NewLargeListData returns a new LargeList array value, from data. +func NewLargeListData(data arrow.ArrayData) *LargeList { + a := new(LargeList) + a.refCount = 1 + a.setData(data.(*Data)) + return a +} + +func (a *LargeList) ListValues() arrow.Array { return a.values } + +func (a *LargeList) ValueStr(i int) string { + if !a.IsValid(i) { + return NullValueStr + } + return string(a.GetOneForMarshal(i).(json.RawMessage)) +} + +func (a *LargeList) String() string { + o := new(strings.Builder) + o.WriteString("[") + for i := 0; i < a.Len(); i++ { + if i > 0 { + o.WriteString(" ") + } + if a.IsNull(i) { + o.WriteString(NullValueStr) + continue + } + sub := a.newListValue(i) + fmt.Fprintf(o, "%v", sub) + sub.Release() + } + o.WriteString("]") + return o.String() +} + +func (a *LargeList) newListValue(i int) arrow.Array { + beg, end := a.ValueOffsets(i) + return NewSlice(a.values, beg, end) +} + +func (a *LargeList) setData(data *Data) { + debug.Assert(len(data.buffers) >= 2, "list data should have 2 buffers") + a.array.setData(data) + vals := data.buffers[1] + if vals != nil { + a.offsets = arrow.Int64Traits.CastFromBytes(vals.Bytes()) + } + a.values = MakeFromData(data.childData[0]) +} + +func (a *LargeList) GetOneForMarshal(i int) interface{} { + if a.IsNull(i) { + return nil + } + + slice := a.newListValue(i) + defer slice.Release() + v, err := json.Marshal(slice) + if err != nil { + panic(err) + } + return json.RawMessage(v) +} + +func (a *LargeList) MarshalJSON() ([]byte, error) { + var buf bytes.Buffer + enc := json.NewEncoder(&buf) + + buf.WriteByte('[') + for i := 0; i < a.Len(); i++ { + if i != 0 { + buf.WriteByte(',') + } + if err := enc.Encode(a.GetOneForMarshal(i)); err != nil { + return nil, err + } + } + buf.WriteByte(']') + return buf.Bytes(), nil +} + +func arrayEqualLargeList(left, right *LargeList) bool { + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + o := func() bool { + l := left.newListValue(i) + defer l.Release() + r := right.newListValue(i) + defer r.Release() + return Equal(l, r) + }() + if !o { + return false + } + } + return true +} + +// Len returns the number of elements in the array. +func (a *LargeList) Len() int { return a.array.Len() } + +func (a *LargeList) Offsets() []int64 { return a.offsets } + +func (a *LargeList) ValueOffsets(i int) (start, end int64) { + debug.Assert(i >= 0 && i < a.array.data.length, "index out of range") + j := i + a.array.data.offset + start, end = a.offsets[j], a.offsets[j+1] + return +} + +func (a *LargeList) Retain() { + a.array.Retain() + a.values.Retain() +} + +func (a *LargeList) Release() { + a.array.Release() + a.values.Release() +} + +type baseListBuilder struct { + builder + + values Builder // value builder for the list's elements. + offsets Builder + + // actual list type + dt arrow.DataType + appendOffsetVal func(int) +} + +type ListLikeBuilder interface { + Builder + ValueBuilder() Builder + Append(bool) +} + +type VarLenListLikeBuilder interface { + ListLikeBuilder + AppendWithSize(bool, int) +} + +type ListBuilder struct { + baseListBuilder +} + +type LargeListBuilder struct { + baseListBuilder +} + +// NewListBuilder returns a builder, using the provided memory allocator. +// The created list builder will create a list whose elements will be of type etype. +func NewListBuilder(mem memory.Allocator, etype arrow.DataType) *ListBuilder { + offsetBldr := NewInt32Builder(mem) + return &ListBuilder{ + baseListBuilder{ + builder: builder{refCount: 1, mem: mem}, + values: NewBuilder(mem, etype), + offsets: offsetBldr, + dt: arrow.ListOf(etype), + appendOffsetVal: func(o int) { offsetBldr.Append(int32(o)) }, + }, + } +} + +// NewListBuilderWithField takes a field to use for the child rather than just +// a datatype to allow for more customization. +func NewListBuilderWithField(mem memory.Allocator, field arrow.Field) *ListBuilder { + offsetBldr := NewInt32Builder(mem) + return &ListBuilder{ + baseListBuilder{ + builder: builder{refCount: 1, mem: mem}, + values: NewBuilder(mem, field.Type), + offsets: offsetBldr, + dt: arrow.ListOfField(field), + appendOffsetVal: func(o int) { offsetBldr.Append(int32(o)) }, + }, + } +} + +func (b *baseListBuilder) Type() arrow.DataType { + switch dt := b.dt.(type) { + case *arrow.ListType: + f := dt.ElemField() + f.Type = b.values.Type() + return arrow.ListOfField(f) + case *arrow.LargeListType: + f := dt.ElemField() + f.Type = b.values.Type() + return arrow.LargeListOfField(f) + } + return nil +} + +// NewLargeListBuilder returns a builder, using the provided memory allocator. +// The created list builder will create a list whose elements will be of type etype. +func NewLargeListBuilder(mem memory.Allocator, etype arrow.DataType) *LargeListBuilder { + offsetBldr := NewInt64Builder(mem) + return &LargeListBuilder{ + baseListBuilder{ + builder: builder{refCount: 1, mem: mem}, + values: NewBuilder(mem, etype), + offsets: offsetBldr, + dt: arrow.LargeListOf(etype), + appendOffsetVal: func(o int) { offsetBldr.Append(int64(o)) }, + }, + } +} + +// NewLargeListBuilderWithField takes a field rather than just an element type +// to allow for more customization of the final type of the LargeList Array +func NewLargeListBuilderWithField(mem memory.Allocator, field arrow.Field) *LargeListBuilder { + offsetBldr := NewInt64Builder(mem) + return &LargeListBuilder{ + baseListBuilder{ + builder: builder{refCount: 1, mem: mem}, + values: NewBuilder(mem, field.Type), + offsets: offsetBldr, + dt: arrow.LargeListOfField(field), + appendOffsetVal: func(o int) { offsetBldr.Append(int64(o)) }, + }, + } +} + +// Release decreases the reference count by 1. +// When the reference count goes to zero, the memory is freed. +func (b *baseListBuilder) Release() { + debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases") + + if atomic.AddInt64(&b.refCount, -1) == 0 { + if b.nullBitmap != nil { + b.nullBitmap.Release() + b.nullBitmap = nil + } + b.values.Release() + b.offsets.Release() + } + +} + +func (b *baseListBuilder) appendNextOffset() { + b.appendOffsetVal(b.values.Len()) +} + +func (b *baseListBuilder) Append(v bool) { + b.Reserve(1) + b.unsafeAppendBoolToBitmap(v) + b.appendNextOffset() +} + +func (b *baseListBuilder) AppendWithSize(v bool, _ int) { + b.Append(v) +} + +func (b *baseListBuilder) AppendNull() { + b.Reserve(1) + b.unsafeAppendBoolToBitmap(false) + b.appendNextOffset() +} + +func (b *baseListBuilder) AppendNulls(n int) { + for i := 0; i < n; i++ { + b.AppendNull() + } +} + +func (b *baseListBuilder) AppendEmptyValue() { + b.Append(true) +} + +func (b *baseListBuilder) AppendEmptyValues(n int) { + for i := 0; i < n; i++ { + b.AppendEmptyValue() + } +} + +func (b *ListBuilder) AppendValues(offsets []int32, valid []bool) { + b.Reserve(len(valid)) + b.offsets.(*Int32Builder).AppendValues(offsets, nil) + b.builder.unsafeAppendBoolsToBitmap(valid, len(valid)) +} + +func (b *LargeListBuilder) AppendValues(offsets []int64, valid []bool) { + b.Reserve(len(valid)) + b.offsets.(*Int64Builder).AppendValues(offsets, nil) + b.builder.unsafeAppendBoolsToBitmap(valid, len(valid)) +} + +func (b *baseListBuilder) unsafeAppendBoolToBitmap(isValid bool) { + if isValid { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + } else { + b.nulls++ + } + b.length++ +} + +func (b *baseListBuilder) init(capacity int) { + b.builder.init(capacity) + b.offsets.init(capacity + 1) +} + +// Reserve ensures there is enough space for appending n elements +// by checking the capacity and calling Resize if necessary. +func (b *baseListBuilder) Reserve(n int) { + b.builder.reserve(n, b.resizeHelper) + b.offsets.Reserve(n) +} + +// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(), +// additional memory will be allocated. If n is smaller, the allocated memory may reduced. +func (b *baseListBuilder) Resize(n int) { + b.resizeHelper(n) + b.offsets.Resize(n) +} + +func (b *baseListBuilder) resizeHelper(n int) { + if n < minBuilderCapacity { + n = minBuilderCapacity + } + + if b.capacity == 0 { + b.init(n) + } else { + b.builder.resize(n, b.builder.init) + } +} + +func (b *baseListBuilder) ValueBuilder() Builder { + return b.values +} + +// NewArray creates a List array from the memory buffers used by the builder and resets the ListBuilder +// so it can be used to build a new array. +func (b *ListBuilder) NewArray() arrow.Array { + return b.NewListArray() +} + +// NewArray creates a LargeList array from the memory buffers used by the builder and resets the LargeListBuilder +// so it can be used to build a new array. +func (b *LargeListBuilder) NewArray() arrow.Array { + return b.NewLargeListArray() +} + +// NewListArray creates a List array from the memory buffers used by the builder and resets the ListBuilder +// so it can be used to build a new array. +func (b *ListBuilder) NewListArray() (a *List) { + data := b.newData() + a = NewListData(data) + data.Release() + return +} + +// NewLargeListArray creates a List array from the memory buffers used by the builder and resets the LargeListBuilder +// so it can be used to build a new array. +func (b *LargeListBuilder) NewLargeListArray() (a *LargeList) { + data := b.newData() + a = NewLargeListData(data) + data.Release() + return +} + +func (b *baseListBuilder) newData() (data *Data) { + if b.offsets.Len() != b.length+1 { + b.appendNextOffset() + } + values := b.values.NewArray() + defer values.Release() + + var offsets *memory.Buffer + if b.offsets != nil { + arr := b.offsets.NewArray() + defer arr.Release() + offsets = arr.Data().Buffers()[1] + } + + data = NewData( + b.Type(), b.length, + []*memory.Buffer{ + b.nullBitmap, + offsets, + }, + []arrow.ArrayData{values.Data()}, + b.nulls, + 0, + ) + b.reset() + + return +} + +func (b *baseListBuilder) AppendValueFromString(s string) error { + if s == NullValueStr { + b.AppendNull() + return nil + } + + return b.UnmarshalOne(json.NewDecoder(strings.NewReader(s))) +} + +func (b *baseListBuilder) UnmarshalOne(dec *json.Decoder) error { + t, err := dec.Token() + if err != nil { + return err + } + + switch t { + case json.Delim('['): + b.Append(true) + if err := b.values.Unmarshal(dec); err != nil { + return err + } + // consume ']' + _, err := dec.Token() + return err + case nil: + b.AppendNull() + default: + return &json.UnmarshalTypeError{ + Value: fmt.Sprint(t), + Struct: b.dt.String(), + } + } + + return nil +} + +func (b *baseListBuilder) Unmarshal(dec *json.Decoder) error { + for dec.More() { + if err := b.UnmarshalOne(dec); err != nil { + return err + } + } + return nil +} + +func (b *baseListBuilder) UnmarshalJSON(data []byte) error { + dec := json.NewDecoder(bytes.NewReader(data)) + t, err := dec.Token() + if err != nil { + return err + } + + if delim, ok := t.(json.Delim); !ok || delim != '[' { + return fmt.Errorf("list builder must unpack from json array, found %s", delim) + } + + return b.Unmarshal(dec) +} + +// ListView represents an immutable sequence of array values defined by an +// offset into a child array and a length. +type ListView struct { + array + values arrow.Array + offsets []int32 + sizes []int32 +} + +var _ VarLenListLike = (*ListView)(nil) + +func NewListViewData(data arrow.ArrayData) *ListView { + a := &ListView{} + a.refCount = 1 + a.setData(data.(*Data)) + return a +} + +func (a *ListView) ListValues() arrow.Array { return a.values } + +func (a *ListView) ValueStr(i int) string { + if !a.IsValid(i) { + return NullValueStr + } + return string(a.GetOneForMarshal(i).(json.RawMessage)) +} + +func (a *ListView) String() string { + o := new(strings.Builder) + o.WriteString("[") + for i := 0; i < a.Len(); i++ { + if i > 0 { + o.WriteString(" ") + } + if a.IsNull(i) { + o.WriteString(NullValueStr) + continue + } + sub := a.newListValue(i) + fmt.Fprintf(o, "%v", sub) + sub.Release() + } + o.WriteString("]") + return o.String() +} + +func (a *ListView) newListValue(i int) arrow.Array { + beg, end := a.ValueOffsets(i) + return NewSlice(a.values, beg, end) +} + +func (a *ListView) setData(data *Data) { + debug.Assert(len(data.buffers) >= 3, "list-view data should have 3 buffers") + a.array.setData(data) + offsets := data.buffers[1] + if offsets != nil { + a.offsets = arrow.Int32Traits.CastFromBytes(offsets.Bytes()) + } + sizes := data.buffers[2] + if sizes != nil { + a.sizes = arrow.Int32Traits.CastFromBytes(sizes.Bytes()) + } + a.values = MakeFromData(data.childData[0]) +} + +func (a *ListView) GetOneForMarshal(i int) interface{} { + if a.IsNull(i) { + return nil + } + + slice := a.newListValue(i) + defer slice.Release() + v, err := json.Marshal(slice) + if err != nil { + panic(err) + } + return json.RawMessage(v) +} + +func (a *ListView) MarshalJSON() ([]byte, error) { + var buf bytes.Buffer + enc := json.NewEncoder(&buf) + + buf.WriteByte('[') + for i := 0; i < a.Len(); i++ { + if i != 0 { + buf.WriteByte(',') + } + if err := enc.Encode(a.GetOneForMarshal(i)); err != nil { + return nil, err + } + } + buf.WriteByte(']') + return buf.Bytes(), nil +} + +func arrayEqualListView(left, right *ListView) bool { + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + o := func() bool { + l := left.newListValue(i) + defer l.Release() + r := right.newListValue(i) + defer r.Release() + return Equal(l, r) + }() + if !o { + return false + } + } + return true +} + +// Len returns the number of elements in the array. +func (a *ListView) Len() int { return a.array.Len() } + +func (a *ListView) Offsets() []int32 { return a.offsets } + +func (a *ListView) Sizes() []int32 { return a.sizes } + +func (a *ListView) Retain() { + a.array.Retain() + a.values.Retain() +} + +func (a *ListView) Release() { + a.array.Release() + a.values.Release() +} + +func (a *ListView) ValueOffsets(i int) (start, end int64) { + debug.Assert(i >= 0 && i < a.array.data.length, "index out of range") + j := i + a.array.data.offset + size := int64(a.sizes[j]) + // If size is 0, skip accessing offsets. + if size == 0 { + start, end = 0, 0 + return + } + start = int64(a.offsets[j]) + end = start + size + return +} + +// LargeListView represents an immutable sequence of array values defined by an +// offset into a child array and a length. +type LargeListView struct { + array + values arrow.Array + offsets []int64 + sizes []int64 +} + +var _ VarLenListLike = (*LargeListView)(nil) + +// NewLargeListViewData returns a new LargeListView array value, from data. +func NewLargeListViewData(data arrow.ArrayData) *LargeListView { + a := new(LargeListView) + a.refCount = 1 + a.setData(data.(*Data)) + return a +} + +func (a *LargeListView) ListValues() arrow.Array { return a.values } + +func (a *LargeListView) ValueStr(i int) string { + if !a.IsValid(i) { + return NullValueStr + } + return string(a.GetOneForMarshal(i).(json.RawMessage)) +} + +func (a *LargeListView) String() string { + o := new(strings.Builder) + o.WriteString("[") + for i := 0; i < a.Len(); i++ { + if i > 0 { + o.WriteString(" ") + } + if a.IsNull(i) { + o.WriteString(NullValueStr) + continue + } + sub := a.newListValue(i) + fmt.Fprintf(o, "%v", sub) + sub.Release() + } + o.WriteString("]") + return o.String() +} + +func (a *LargeListView) newListValue(i int) arrow.Array { + beg, end := a.ValueOffsets(i) + return NewSlice(a.values, beg, end) +} + +func (a *LargeListView) setData(data *Data) { + debug.Assert(len(data.buffers) >= 3, "list-view data should have 3 buffers") + a.array.setData(data) + offsets := data.buffers[1] + if offsets != nil { + a.offsets = arrow.Int64Traits.CastFromBytes(offsets.Bytes()) + } + sizes := data.buffers[2] + if sizes != nil { + a.sizes = arrow.Int64Traits.CastFromBytes(sizes.Bytes()) + } + a.values = MakeFromData(data.childData[0]) +} + +func (a *LargeListView) GetOneForMarshal(i int) interface{} { + if a.IsNull(i) { + return nil + } + + slice := a.newListValue(i) + defer slice.Release() + v, err := json.Marshal(slice) + if err != nil { + panic(err) + } + return json.RawMessage(v) +} + +func (a *LargeListView) MarshalJSON() ([]byte, error) { + var buf bytes.Buffer + enc := json.NewEncoder(&buf) + + buf.WriteByte('[') + for i := 0; i < a.Len(); i++ { + if i != 0 { + buf.WriteByte(',') + } + if err := enc.Encode(a.GetOneForMarshal(i)); err != nil { + return nil, err + } + } + buf.WriteByte(']') + return buf.Bytes(), nil +} + +func arrayEqualLargeListView(left, right *LargeListView) bool { + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + o := func() bool { + l := left.newListValue(i) + defer l.Release() + r := right.newListValue(i) + defer r.Release() + return Equal(l, r) + }() + if !o { + return false + } + } + return true +} + +// Len returns the number of elements in the array. +func (a *LargeListView) Len() int { return a.array.Len() } + +func (a *LargeListView) Offsets() []int64 { return a.offsets } + +func (a *LargeListView) Sizes() []int64 { return a.sizes } + +func (a *LargeListView) ValueOffsets(i int) (start, end int64) { + debug.Assert(i >= 0 && i < a.array.data.length, "index out of range") + j := i + a.array.data.offset + size := a.sizes[j] + // If size is 0, skip accessing offsets. + if size == 0 { + return 0, 0 + } + start = a.offsets[j] + end = start + size + return +} + +func (a *LargeListView) Retain() { + a.array.Retain() + a.values.Retain() +} + +func (a *LargeListView) Release() { + a.array.Release() + a.values.Release() +} + +// Acessors for offsets and sizes to make ListView and LargeListView validation generic. +type offsetsAndSizes interface { + offsetAt(slot int64) int64 + sizeAt(slot int64) int64 +} + +var _ offsetsAndSizes = (*ListView)(nil) +var _ offsetsAndSizes = (*LargeListView)(nil) + +func (a *ListView) offsetAt(slot int64) int64 { return int64(a.offsets[int64(a.data.offset)+slot]) } + +func (a *ListView) sizeAt(slot int64) int64 { return int64(a.sizes[int64(a.data.offset)+slot]) } + +func (a *LargeListView) offsetAt(slot int64) int64 { return a.offsets[int64(a.data.offset)+slot] } + +func (a *LargeListView) sizeAt(slot int64) int64 { return a.sizes[int64(a.data.offset)+slot] } + +func outOfBoundsListViewOffset(l offsetsAndSizes, slot int64, offsetLimit int64) error { + offset := l.offsetAt(slot) + return fmt.Errorf("%w: Offset invariant failure: offset for slot %d out of bounds. Expected %d to be at least 0 and less than %d", arrow.ErrInvalid, slot, offset, offsetLimit) +} + +func outOfBoundsListViewSize(l offsetsAndSizes, slot int64, offsetLimit int64) error { + size := l.sizeAt(slot) + if size < 0 { + return fmt.Errorf("%w: Offset invariant failure: size for slot %d out of bounds: %d < 0", arrow.ErrInvalid, slot, size) + } + offset := l.offsetAt(slot) + return fmt.Errorf("%w: Offset invariant failure: size for slot %d out of bounds: %d + %d > %d", arrow.ErrInvalid, slot, offset, size, offsetLimit) +} + +// Pre-condition: Basic validation has already been performed +func (a *array) fullyValidateOffsetsAndSizes(l offsetsAndSizes, offsetLimit int64) error { + for slot := int64(0); slot < int64(a.Len()); slot += 1 { + size := l.sizeAt(slot) + if size > 0 { + offset := l.offsetAt(slot) + if offset < 0 || offset > offsetLimit { + return outOfBoundsListViewOffset(l, slot, offsetLimit) + } + if size > offsetLimit-int64(offset) { + return outOfBoundsListViewSize(l, slot, offsetLimit) + } + } else if size < 0 { + return outOfBoundsListViewSize(l, slot, offsetLimit) + } + } + + return nil +} + +func (a *array) validateOffsetsAndMaybeSizes(l offsetsAndSizes, offsetByteWidth int, isListView bool, offsetLimit int64, fullValidation bool) error { + nonEmpty := a.Len() > 0 + if a.data.buffers[1] == nil { + // For length 0, an empty offsets buffer is accepted (ARROW-544). + if nonEmpty { + return fmt.Errorf("non-empty array but offsets are null") + } + return nil + } + if isListView && a.data.buffers[2] == nil { + if nonEmpty { + return fmt.Errorf("non-empty array but sizes are null") + } + return nil + } + + var requiredOffsets int + if nonEmpty { + requiredOffsets = a.Len() + a.Offset() + if !isListView { + requiredOffsets += 1 + } + } else { + requiredOffsets = 0 + } + offsetsByteSize := a.data.buffers[1].Len() + if offsetsByteSize/offsetByteWidth < requiredOffsets { + return fmt.Errorf("offsets buffer size (bytes): %d isn't large enough for length: %d and offset: %d", + offsetsByteSize, a.Len(), a.Offset()) + } + if isListView { + requiredSizes := a.Len() + a.Offset() + sizesBytesSize := a.data.buffers[2].Len() + if sizesBytesSize/offsetByteWidth < requiredSizes { + return fmt.Errorf("sizes buffer size (bytes): %d isn't large enough for length: %d and offset: %d", + sizesBytesSize, a.Len(), a.Offset()) + } + } + + if fullValidation && requiredOffsets > 0 { + if isListView { + return a.fullyValidateOffsetsAndSizes(l, offsetLimit) + } + // TODO: implement validation of List and LargeList + // return fullyValidateOffsets(offset_limit) + return nil + } + return nil +} + +func (a *ListView) validate(fullValidation bool) error { + values := a.array.data.childData[0] + offsetLimit := values.Len() + return a.array.validateOffsetsAndMaybeSizes(a, 4, true, int64(offsetLimit), fullValidation) +} + +func (a *ListView) Validate() error { + return a.validate(false) +} + +func (a *ListView) ValidateFull() error { + return a.validate(true) +} + +func (a *LargeListView) validate(fullValidation bool) error { + values := a.array.data.childData[0] + offsetLimit := values.Len() + return a.array.validateOffsetsAndMaybeSizes(a, 8, true, int64(offsetLimit), fullValidation) +} + +func (a *LargeListView) Validate() error { + return a.validate(false) +} + +func (a *LargeListView) ValidateFull() error { + return a.validate(true) +} + +type baseListViewBuilder struct { + builder + + values Builder // value builder for the list-view's elements. + offsets Builder + sizes Builder + + // actual list-view type + dt arrow.DataType + appendOffsetVal func(int) + appendSizeVal func(int) +} + +type ListViewBuilder struct { + baseListViewBuilder +} + +type LargeListViewBuilder struct { + baseListViewBuilder +} + +// NewListViewBuilder returns a builder, using the provided memory allocator. +// The created list-view builder will create a list whose elements will be +// of type etype. +func NewListViewBuilder(mem memory.Allocator, etype arrow.DataType) *ListViewBuilder { + offsetBldr := NewInt32Builder(mem) + sizeBldr := NewInt32Builder(mem) + return &ListViewBuilder{ + baseListViewBuilder{ + builder: builder{refCount: 1, mem: mem}, + values: NewBuilder(mem, etype), + offsets: offsetBldr, + sizes: sizeBldr, + dt: arrow.ListViewOf(etype), + appendOffsetVal: func(o int) { offsetBldr.Append(int32(o)) }, + appendSizeVal: func(s int) { sizeBldr.Append(int32(s)) }, + }, + } +} + +// NewListViewBuilderWithField takes a field to use for the child rather than just +// a datatype to allow for more customization. +func NewListViewBuilderWithField(mem memory.Allocator, field arrow.Field) *ListViewBuilder { + offsetBldr := NewInt32Builder(mem) + sizeBldr := NewInt32Builder(mem) + return &ListViewBuilder{ + baseListViewBuilder{ + builder: builder{refCount: 1, mem: mem}, + values: NewBuilder(mem, field.Type), + offsets: offsetBldr, + sizes: sizeBldr, + dt: arrow.ListViewOfField(field), + appendOffsetVal: func(o int) { offsetBldr.Append(int32(o)) }, + appendSizeVal: func(s int) { sizeBldr.Append(int32(s)) }, + }, + } +} + +func (b *baseListViewBuilder) Type() arrow.DataType { + switch dt := b.dt.(type) { + case *arrow.ListViewType: + f := dt.ElemField() + f.Type = b.values.Type() + return arrow.ListViewOfField(f) + case *arrow.LargeListViewType: + f := dt.ElemField() + f.Type = b.values.Type() + return arrow.LargeListViewOfField(f) + } + return nil +} + +// NewLargeListViewBuilder returns a builder, using the provided memory allocator. +// The created list-view builder will create a list whose elements will be of type etype. +func NewLargeListViewBuilder(mem memory.Allocator, etype arrow.DataType) *LargeListViewBuilder { + offsetBldr := NewInt64Builder(mem) + sizeBldr := NewInt64Builder(mem) + return &LargeListViewBuilder{ + baseListViewBuilder{ + builder: builder{refCount: 1, mem: mem}, + values: NewBuilder(mem, etype), + offsets: offsetBldr, + sizes: sizeBldr, + dt: arrow.LargeListViewOf(etype), + appendOffsetVal: func(o int) { offsetBldr.Append(int64(o)) }, + appendSizeVal: func(s int) { sizeBldr.Append(int64(s)) }, + }, + } +} + +// NewLargeListViewBuilderWithField takes a field rather than just an element type +// to allow for more customization of the final type of the LargeListView Array +func NewLargeListViewBuilderWithField(mem memory.Allocator, field arrow.Field) *LargeListViewBuilder { + offsetBldr := NewInt64Builder(mem) + sizeBldr := NewInt64Builder(mem) + return &LargeListViewBuilder{ + baseListViewBuilder{ + builder: builder{refCount: 1, mem: mem}, + values: NewBuilder(mem, field.Type), + offsets: offsetBldr, + sizes: sizeBldr, + dt: arrow.LargeListViewOfField(field), + appendOffsetVal: func(o int) { offsetBldr.Append(int64(o)) }, + appendSizeVal: func(o int) { sizeBldr.Append(int64(o)) }, + }, + } +} + +// Release decreases the reference count by 1. +// When the reference count goes to zero, the memory is freed. +func (b *baseListViewBuilder) Release() { + debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases") + + if atomic.AddInt64(&b.refCount, -1) == 0 { + if b.nullBitmap != nil { + b.nullBitmap.Release() + b.nullBitmap = nil + } + b.values.Release() + b.offsets.Release() + b.sizes.Release() + } +} + +func (b *baseListViewBuilder) AppendDimensions(offset int, listSize int) { + b.Reserve(1) + b.unsafeAppendBoolToBitmap(true) + b.appendOffsetVal(offset) + b.appendSizeVal(listSize) +} + +func (b *baseListViewBuilder) Append(v bool) { + debug.Assert(false, "baseListViewBuilder.Append should never be called -- use AppendWithSize instead") +} + +func (b *baseListViewBuilder) AppendWithSize(v bool, listSize int) { + debug.Assert(v || listSize == 0, "invalid list-view should have size 0") + b.Reserve(1) + b.unsafeAppendBoolToBitmap(v) + b.appendOffsetVal(b.values.Len()) + b.appendSizeVal(listSize) +} + +func (b *baseListViewBuilder) AppendNull() { + b.AppendWithSize(false, 0) +} + +func (b *baseListViewBuilder) AppendNulls(n int) { + for i := 0; i < n; i++ { + b.AppendNull() + } +} + +func (b *baseListViewBuilder) AppendEmptyValue() { + b.AppendWithSize(true, 0) +} + +func (b *baseListViewBuilder) AppendEmptyValues(n int) { + for i := 0; i < n; i++ { + b.AppendEmptyValue() + } +} + +func (b *ListViewBuilder) AppendValuesWithSizes(offsets []int32, sizes []int32, valid []bool) { + b.Reserve(len(valid)) + b.offsets.(*Int32Builder).AppendValues(offsets, nil) + b.sizes.(*Int32Builder).AppendValues(sizes, nil) + b.builder.unsafeAppendBoolsToBitmap(valid, len(valid)) +} + +func (b *LargeListViewBuilder) AppendValuesWithSizes(offsets []int64, sizes []int64, valid []bool) { + b.Reserve(len(valid)) + b.offsets.(*Int64Builder).AppendValues(offsets, nil) + b.sizes.(*Int64Builder).AppendValues(sizes, nil) + b.builder.unsafeAppendBoolsToBitmap(valid, len(valid)) +} + +func (b *baseListViewBuilder) unsafeAppendBoolToBitmap(isValid bool) { + if isValid { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + } else { + b.nulls++ + } + b.length++ +} + +func (b *baseListViewBuilder) init(capacity int) { + b.builder.init(capacity) + b.offsets.init(capacity) + b.sizes.init(capacity) +} + +// Reserve ensures there is enough space for appending n elements +// by checking the capacity and calling Resize if necessary. +func (b *baseListViewBuilder) Reserve(n int) { + b.builder.reserve(n, b.resizeHelper) + b.offsets.Reserve(n) + b.sizes.Reserve(n) +} + +// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(), +// additional memory will be allocated. If n is smaller, the allocated memory may reduced. +func (b *baseListViewBuilder) Resize(n int) { + b.resizeHelper(n) + b.offsets.Resize(n) + b.sizes.Resize(n) +} + +func (b *baseListViewBuilder) resizeHelper(n int) { + if n < minBuilderCapacity { + n = minBuilderCapacity + } + + if b.capacity == 0 { + b.init(n) + } else { + b.builder.resize(n, b.builder.init) + } +} + +func (b *baseListViewBuilder) ValueBuilder() Builder { + return b.values +} + +// NewArray creates a ListView array from the memory buffers used by the builder and +// resets the ListViewBuilder so it can be used to build a new array. +func (b *ListViewBuilder) NewArray() arrow.Array { + return b.NewListViewArray() +} + +// NewArray creates a LargeListView array from the memory buffers used by the builder +// and resets the LargeListViewBuilder so it can be used to build a new array. +func (b *LargeListViewBuilder) NewArray() arrow.Array { + return b.NewLargeListViewArray() +} + +// NewListViewArray creates a ListView array from the memory buffers used by the builder +// and resets the ListViewBuilder so it can be used to build a new array. +func (b *ListViewBuilder) NewListViewArray() (a *ListView) { + data := b.newData() + a = NewListViewData(data) + data.Release() + return +} + +// NewLargeListViewArray creates a ListView array from the memory buffers used by the +// builder and resets the LargeListViewBuilder so it can be used to build a new array. +func (b *LargeListViewBuilder) NewLargeListViewArray() (a *LargeListView) { + data := b.newData() + a = NewLargeListViewData(data) + data.Release() + return +} + +func (b *baseListViewBuilder) newData() (data *Data) { + values := b.values.NewArray() + defer values.Release() + + var offsets *memory.Buffer + if b.offsets != nil { + arr := b.offsets.NewArray() + defer arr.Release() + offsets = arr.Data().Buffers()[1] + } + + var sizes *memory.Buffer + if b.sizes != nil { + arr := b.sizes.NewArray() + defer arr.Release() + sizes = arr.Data().Buffers()[1] + } + + data = NewData( + b.Type(), b.length, + []*memory.Buffer{ + b.nullBitmap, + offsets, + sizes, + }, + []arrow.ArrayData{values.Data()}, + b.nulls, + 0, + ) + b.reset() + + return +} + +func (b *baseListViewBuilder) AppendValueFromString(s string) error { + if s == NullValueStr { + b.AppendNull() + return nil + } + + return b.UnmarshalOne(json.NewDecoder(strings.NewReader(s))) +} + +func (b *baseListViewBuilder) UnmarshalOne(dec *json.Decoder) error { + t, err := dec.Token() + if err != nil { + return err + } + + switch t { + case json.Delim('['): + offset := b.values.Len() + // 0 is a placeholder size as we don't know the actual size yet + b.AppendWithSize(true, 0) + if err := b.values.Unmarshal(dec); err != nil { + return err + } + // consume ']' + _, err := dec.Token() + // replace the last size with the actual size + switch b.sizes.(type) { + case *Int32Builder: + b.sizes.(*Int32Builder).rawData[b.sizes.Len()-1] = int32(b.values.Len() - offset) + case *Int64Builder: + b.sizes.(*Int64Builder).rawData[b.sizes.Len()-1] = int64(b.values.Len() - offset) + } + return err + case nil: + b.AppendNull() + default: + return &json.UnmarshalTypeError{ + Value: fmt.Sprint(t), + Struct: b.dt.String(), + } + } + + return nil +} + +func (b *baseListViewBuilder) Unmarshal(dec *json.Decoder) error { + for dec.More() { + if err := b.UnmarshalOne(dec); err != nil { + return err + } + } + return nil +} + +func (b *baseListViewBuilder) UnmarshalJSON(data []byte) error { + dec := json.NewDecoder(bytes.NewReader(data)) + t, err := dec.Token() + if err != nil { + return err + } + + if delim, ok := t.(json.Delim); !ok || delim != '[' { + return fmt.Errorf("list-view builder must unpack from json array, found %s", delim) + } + + return b.Unmarshal(dec) +} + +// Pre-conditions: +// +// input.DataType() is ListViewType +// input.Len() > 0 && input.NullN() != input.Len() +func minListViewOffset32(input arrow.ArrayData) int32 { + var bitmap []byte + if input.Buffers()[0] != nil { + bitmap = input.Buffers()[0].Bytes() + } + offsets := arrow.Int32Traits.CastFromBytes(input.Buffers()[1].Bytes())[input.Offset():] + sizes := arrow.Int32Traits.CastFromBytes(input.Buffers()[2].Bytes())[input.Offset():] + + isNull := func(i int) bool { + return bitmap != nil && bitutil.BitIsNotSet(bitmap, input.Offset()+i) + } + + // It's very likely that the first non-null non-empty list-view starts at + // offset 0 of the child array. + i := 0 + for i < input.Len() && (isNull(i) || sizes[i] == 0) { + i += 1 + } + if i >= input.Len() { + return 0 + } + minOffset := offsets[i] + if minOffset == 0 { + // early exit: offset 0 found already + return 0 + } + + // Slow path: scan the buffers entirely. + i += 1 + for ; i < input.Len(); i += 1 { + if isNull(i) { + continue + } + offset := offsets[i] + if offset < minOffset && sizes[i] > 0 { + minOffset = offset + } + } + return minOffset +} + +// Find the maximum offset+size in a LIST_VIEW array. +// +// Pre-conditions: +// +// input.DataType() is ListViewType +// input.Len() > 0 && input.NullN() != input.Len() +func maxListViewOffset32(input arrow.ArrayData) int { + inputOffset := input.Offset() + var bitmap []byte + if input.Buffers()[0] != nil { + bitmap = input.Buffers()[0].Bytes() + } + offsets := arrow.Int32Traits.CastFromBytes(input.Buffers()[1].Bytes())[inputOffset:] + sizes := arrow.Int32Traits.CastFromBytes(input.Buffers()[2].Bytes())[inputOffset:] + + isNull := func(i int) bool { + return bitmap != nil && bitutil.BitIsNotSet(bitmap, inputOffset+i) + } + + i := input.Len() - 1 // safe because input.Len() > 0 + for i != 0 && (isNull(i) || sizes[i] == 0) { + i -= 1 + } + offset := offsets[i] + size := sizes[i] + if i == 0 { + if isNull(i) || sizes[i] == 0 { + return 0 + } else { + return int(offset + size) + } + } + + values := input.Children()[0] + maxEnd := int(offsets[i] + sizes[i]) + if maxEnd == values.Len() { + // Early-exit: maximum possible view-end found already. + return maxEnd + } + + // Slow path: scan the buffers entirely. + for ; i >= 0; i -= 1 { + offset := offsets[i] + size := sizes[i] + if size > 0 && !isNull(i) { + if int(offset+size) > maxEnd { + maxEnd = int(offset + size) + if maxEnd == values.Len() { + return maxEnd + } + } + } + } + return maxEnd +} + +// Pre-conditions: +// +// input.DataType() is LargeListViewType +// input.Len() > 0 && input.NullN() != input.Len() +func minLargeListViewOffset64(input arrow.ArrayData) int64 { + var bitmap []byte + if input.Buffers()[0] != nil { + bitmap = input.Buffers()[0].Bytes() + } + offsets := arrow.Int64Traits.CastFromBytes(input.Buffers()[1].Bytes())[input.Offset():] + sizes := arrow.Int64Traits.CastFromBytes(input.Buffers()[2].Bytes())[input.Offset():] + + isNull := func(i int) bool { + return bitmap != nil && bitutil.BitIsNotSet(bitmap, input.Offset()+i) + } + + // It's very likely that the first non-null non-empty list-view starts at + // offset 0 of the child array. + i := 0 + for i < input.Len() && (isNull(i) || sizes[i] == 0) { + i += 1 + } + if i >= input.Len() { + return 0 + } + minOffset := offsets[i] + if minOffset == 0 { + // early exit: offset 0 found already + return 0 + } + + // Slow path: scan the buffers entirely. + i += 1 + for ; i < input.Len(); i += 1 { + if isNull(i) { + continue + } + offset := offsets[i] + if offset < minOffset && sizes[i] > 0 { + minOffset = offset + } + } + return minOffset +} + +// Find the maximum offset+size in a LARGE_LIST_VIEW array. +// +// Pre-conditions: +// +// input.DataType() is LargeListViewType +// input.Len() > 0 && input.NullN() != input.Len() +func maxLargeListViewOffset64(input arrow.ArrayData) int64 { + inputOffset := input.Offset() + var bitmap []byte + if input.Buffers()[0] != nil { + bitmap = input.Buffers()[0].Bytes() + } + offsets := arrow.Int64Traits.CastFromBytes(input.Buffers()[1].Bytes())[inputOffset:] + sizes := arrow.Int64Traits.CastFromBytes(input.Buffers()[2].Bytes())[inputOffset:] + + isNull := func(i int) bool { + return bitmap != nil && bitutil.BitIsNotSet(bitmap, inputOffset+i) + } + + // It's very likely that the first non-null non-empty list-view starts at + // offset zero, so we check that first and potentially early-return a 0. + i := input.Len() - 1 // safe because input.Len() > 0 + for i != 0 && (isNull(i) || sizes[i] == 0) { + i -= 1 + } + offset := offsets[i] + size := sizes[i] + if i == 0 { + if isNull(i) || sizes[i] == 0 { + return 0 + } else { + return offset + size + } + } + + if offset > math.MaxInt64-size { + // Early-exit: 64-bit overflow detected. This is not possible on a + // valid list-view, but we return the maximum possible value to + // avoid undefined behavior. + return math.MaxInt64 + } + values := input.Children()[0] + maxEnd := offsets[i] + sizes[i] + if maxEnd == int64(values.Len()) { + // Early-exit: maximum possible view-end found already. + return maxEnd + } + + // Slow path: scan the buffers entirely. + for ; i >= 0; i -= 1 { + offset := offsets[i] + size := sizes[i] + if size > 0 && !isNull(i) { + if offset+size > maxEnd { + if offset > math.MaxInt64-size { + // 64-bit overflow detected. This is not possible on a valid list-view, + // but we saturate maxEnd to the maximum possible value to avoid + // undefined behavior. + return math.MaxInt64 + } + maxEnd = offset + size + if maxEnd == int64(values.Len()) { + return maxEnd + } + } + } + } + return maxEnd +} + +func rangeOfValuesUsed(input arrow.ArrayData) (int, int) { + if input.Len() == 0 || input.NullN() == input.Len() { + return 0, 0 + } + var minOffset, maxEnd int + switch input.DataType().(type) { + case *arrow.ListViewType: + minOffset = int(minListViewOffset32(input)) + maxEnd = maxListViewOffset32(input) + case *arrow.LargeListViewType: + minOffset = int(minLargeListViewOffset64(input)) + maxEnd = int(maxLargeListViewOffset64(input)) + case *arrow.ListType: + offsets := arrow.Int32Traits.CastFromBytes(input.Buffers()[1].Bytes())[input.Offset():] + minOffset = int(offsets[0]) + maxEnd = int(offsets[len(offsets)-1]) + case *arrow.LargeListType: + offsets := arrow.Int64Traits.CastFromBytes(input.Buffers()[1].Bytes())[input.Offset():] + minOffset = int(offsets[0]) + maxEnd = int(offsets[len(offsets)-1]) + case *arrow.MapType: + offsets := arrow.Int32Traits.CastFromBytes(input.Buffers()[1].Bytes())[input.Offset():] + minOffset = int(offsets[0]) + maxEnd = int(offsets[len(offsets)-1]) + } + return minOffset, maxEnd - minOffset +} + +// Returns the smallest contiguous range of values of the child array that are +// referenced by all the list values in the input array. +func RangeOfValuesUsed(input VarLenListLike) (int, int) { + return rangeOfValuesUsed(input.Data()) +} + +var ( + _ arrow.Array = (*List)(nil) + _ arrow.Array = (*LargeList)(nil) + _ arrow.Array = (*ListView)(nil) + _ arrow.Array = (*LargeListView)(nil) + + _ Builder = (*ListBuilder)(nil) + _ Builder = (*LargeListBuilder)(nil) + _ Builder = (*ListViewBuilder)(nil) + _ Builder = (*LargeListViewBuilder)(nil) + + _ VarLenListLike = (*List)(nil) + _ VarLenListLike = (*LargeList)(nil) + _ VarLenListLike = (*Map)(nil) + _ VarLenListLike = (*ListView)(nil) + _ VarLenListLike = (*LargeListView)(nil) + _ ListLike = (*FixedSizeList)(nil) + + _ VarLenListLikeBuilder = (*ListBuilder)(nil) + _ VarLenListLikeBuilder = (*LargeListBuilder)(nil) + _ VarLenListLikeBuilder = (*ListBuilder)(nil) + _ VarLenListLikeBuilder = (*LargeListBuilder)(nil) + _ VarLenListLikeBuilder = (*MapBuilder)(nil) + _ ListLikeBuilder = (*FixedSizeListBuilder)(nil) +) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array/map.go b/vendor/github.com/apache/arrow/go/v14/arrow/array/map.go new file mode 100644 index 000000000..9945a90ce --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array/map.go @@ -0,0 +1,361 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package array + +import ( + "bytes" + "fmt" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/memory" + "github.com/apache/arrow/go/v14/internal/json" +) + +// Map represents an immutable sequence of Key/Value structs. It is a +// logical type that is implemented as a List. +type Map struct { + *List + keys, items arrow.Array +} + +var _ ListLike = (*Map)(nil) + +// NewMapData returns a new Map array value, from data +func NewMapData(data arrow.ArrayData) *Map { + a := &Map{List: &List{}} + a.refCount = 1 + a.setData(data.(*Data)) + return a +} + +// KeysSorted checks the datatype that was used to construct this array and +// returns the KeysSorted boolean value used to denote if the key array is +// sorted for each list element. +// +// Important note: Nothing is enforced regarding the KeysSorted value, it is +// solely a metadata field that should be set if keys within each value are sorted. +// This value is not used at all in regards to comparisons / equality. +func (a *Map) KeysSorted() bool { return a.DataType().(*arrow.MapType).KeysSorted } + +func (a *Map) validateData(data *Data) { + if len(data.childData) != 1 || data.childData[0] == nil { + panic("arrow/array: expected one child array for map array") + } + + if data.childData[0].DataType().ID() != arrow.STRUCT { + panic("arrow/array: map array child should be struct type") + } + + if data.childData[0].NullN() != 0 { + panic("arrow/array: map array child array should have no nulls") + } + + if len(data.childData[0].Children()) != 2 { + panic("arrow/array: map array child array should have two fields") + } + + if data.childData[0].Children()[0].NullN() != 0 { + panic("arrow/array: map array keys array should have no nulls") + } +} + +func (a *Map) setData(data *Data) { + a.validateData(data) + + a.List.setData(data) + a.keys = MakeFromData(data.childData[0].Children()[0]) + a.items = MakeFromData(data.childData[0].Children()[1]) +} + +// Keys returns the full Array of Key values, equivalent to grabbing +// the key field of the child struct. +func (a *Map) Keys() arrow.Array { return a.keys } + +// Items returns the full Array of Item values, equivalent to grabbing +// the Value field (the second field) of the child struct. +func (a *Map) Items() arrow.Array { return a.items } + +// Retain increases the reference count by 1. +// Retain may be called simultaneously from multiple goroutines. +func (a *Map) Retain() { + a.List.Retain() + a.keys.Retain() + a.items.Retain() +} + +// Release decreases the reference count by 1. +// Release may be called simultaneously from multiple goroutines. +// When the reference count goes to zero, the memory is freed. +func (a *Map) Release() { + a.List.Release() + a.keys.Release() + a.items.Release() +} + +func arrayEqualMap(left, right *Map) bool { + // since Map is implemented using a list, we can just use arrayEqualList + return arrayEqualList(left.List, right.List) +} + +type MapBuilder struct { + listBuilder *ListBuilder + + etype *arrow.MapType + keytype, itemtype arrow.DataType + keyBuilder, itemBuilder Builder + keysSorted bool +} + +// NewMapBuilder returns a builder, using the provided memory allocator. +// The created Map builder will create a map array whose keys will be a non-nullable +// array of type `keytype` and whose mapped items will be a nullable array of itemtype. +// +// KeysSorted is not enforced at all by the builder, it should only be set to true +// building using keys in sorted order for each value. The KeysSorted value will just be +// used when creating the DataType for the map. +// +// # Example +// +// Simple example provided of converting a []map[string]int32 to an array.Map +// by using a MapBuilder: +// +// /* assume maplist == []map[string]int32 */ +// bldr := array.NewMapBuilder(memory.DefaultAllocator, arrow.BinaryTypes.String, arrow.PrimitiveTypes.Int32, false) +// defer bldr.Release() +// kb := bldr.KeyBuilder().(*array.StringBuilder) +// ib := bldr.ItemBuilder().(*array.Int32Builder) +// for _, m := range maplist { +// bldr.Append(true) +// for k, v := range m { +// kb.Append(k) +// ib.Append(v) +// } +// } +// maparr := bldr.NewMapArray() +// defer maparr.Release() +func NewMapBuilder(mem memory.Allocator, keytype, itemtype arrow.DataType, keysSorted bool) *MapBuilder { + etype := arrow.MapOf(keytype, itemtype) + etype.KeysSorted = keysSorted + listBldr := NewListBuilder(mem, etype.Elem()) + keyBldr := listBldr.ValueBuilder().(*StructBuilder).FieldBuilder(0) + keyBldr.Retain() + itemBldr := listBldr.ValueBuilder().(*StructBuilder).FieldBuilder(1) + itemBldr.Retain() + return &MapBuilder{ + listBuilder: listBldr, + keyBuilder: keyBldr, + itemBuilder: itemBldr, + etype: etype, + keytype: keytype, + itemtype: itemtype, + keysSorted: keysSorted, + } +} + +func NewMapBuilderWithType(mem memory.Allocator, dt *arrow.MapType) *MapBuilder { + listBldr := NewListBuilder(mem, dt.Elem()) + keyBldr := listBldr.ValueBuilder().(*StructBuilder).FieldBuilder(0) + keyBldr.Retain() + itemBldr := listBldr.ValueBuilder().(*StructBuilder).FieldBuilder(1) + itemBldr.Retain() + return &MapBuilder{ + listBuilder: listBldr, + keyBuilder: keyBldr, + itemBuilder: itemBldr, + etype: dt, + keytype: dt.KeyType(), + itemtype: dt.ItemType(), + keysSorted: dt.KeysSorted, + } +} + +func (b *MapBuilder) Type() arrow.DataType { return b.etype } + +// Retain increases the reference count by 1 for the sub-builders (list, key, item). +// Retain may be called simultaneously from multiple goroutines. +func (b *MapBuilder) Retain() { + b.listBuilder.Retain() + b.keyBuilder.Retain() + b.itemBuilder.Retain() +} + +// Release decreases the reference count by 1 for the sub builders (list, key, item). +func (b *MapBuilder) Release() { + b.listBuilder.Release() + b.keyBuilder.Release() + b.itemBuilder.Release() +} + +// Len returns the current number of Maps that are in the builder +func (b *MapBuilder) Len() int { return b.listBuilder.Len() } + +// Cap returns the total number of elements that can be stored +// without allocating additional memory. +func (b *MapBuilder) Cap() int { return b.listBuilder.Cap() } + +// NullN returns the number of null values in the array builder. +func (b *MapBuilder) NullN() int { return b.listBuilder.NullN() } + +// IsNull returns if a previously appended value at a given index is null or not. +func (b *MapBuilder) IsNull(i int) bool { + return b.listBuilder.IsNull(i) +} + +// Append adds a new Map element to the array, calling Append(false) is +// equivalent to calling AppendNull. +func (b *MapBuilder) Append(v bool) { + b.adjustStructBuilderLen() + b.listBuilder.Append(v) +} + +func (b *MapBuilder) AppendWithSize(v bool, _ int) { + b.Append(v) +} + +// AppendNull adds a null map entry to the array. +func (b *MapBuilder) AppendNull() { + b.Append(false) +} + +// AppendNulls adds null map entry to the array. +func (b *MapBuilder) AppendNulls(n int) { + for i := 0; i < n; i++ { + b.AppendNull() + } +} + +func (b *MapBuilder) SetNull(i int) { + b.listBuilder.SetNull(i) +} + +func (b *MapBuilder) AppendEmptyValue() { + b.Append(true) +} + +func (b *MapBuilder) AppendEmptyValues(n int) { + for i := 0; i < n; i++ { + b.AppendEmptyValue() + } +} + +// Reserve enough space for n maps +func (b *MapBuilder) Reserve(n int) { b.listBuilder.Reserve(n) } + +// Resize adjust the space allocated by b to n map elements. If n is greater than +// b.Cap(), additional memory will be allocated. If n is smaller, the allocated memory may be reduced. +func (b *MapBuilder) Resize(n int) { b.listBuilder.Resize(n) } + +// AppendValues is for bulk appending a group of elements with offsets provided +// and validity booleans provided. +func (b *MapBuilder) AppendValues(offsets []int32, valid []bool) { + b.adjustStructBuilderLen() + b.listBuilder.AppendValues(offsets, valid) +} + +func (b *MapBuilder) UnsafeAppendBoolToBitmap(v bool) { + b.listBuilder.UnsafeAppendBoolToBitmap(v) +} + +func (b *MapBuilder) init(capacity int) { b.listBuilder.init(capacity) } +func (b *MapBuilder) resize(newBits int, init func(int)) { b.listBuilder.resize(newBits, init) } + +func (b *MapBuilder) adjustStructBuilderLen() { + sb := b.listBuilder.ValueBuilder().(*StructBuilder) + if sb.Len() < b.keyBuilder.Len() { + valids := make([]bool, b.keyBuilder.Len()-sb.Len()) + for i := range valids { + valids[i] = true + } + sb.AppendValues(valids) + } +} + +// NewArray creates a new Map array from the memory buffers used by the builder, and +// resets the builder so it can be used again to build a new Map array. +func (b *MapBuilder) NewArray() arrow.Array { + return b.NewMapArray() +} + +// NewMapArray creates a new Map array from the memory buffers used by the builder, and +// resets the builder so it can be used again to build a new Map array. +func (b *MapBuilder) NewMapArray() (a *Map) { + if !b.etype.ItemField().Nullable && b.ItemBuilder().NullN() > 0 { + panic("arrow/array: item not nullable") + } + + data := b.newData() + defer data.Release() + a = NewMapData(data) + return +} + +func (b *MapBuilder) newData() (data *Data) { + b.adjustStructBuilderLen() + values := b.listBuilder.NewListArray() + defer values.Release() + + data = NewData(b.etype, + values.Len(), values.data.buffers, + values.data.childData, values.NullN(), 0) + return +} + +// KeyBuilder returns a builder that can be used to populate the keys of the maps. +func (b *MapBuilder) KeyBuilder() Builder { return b.keyBuilder } + +// ItemBuilder returns a builder that can be used to populate the values that the +// keys point to. +func (b *MapBuilder) ItemBuilder() Builder { return b.itemBuilder } + +// ValueBuilder can be used instead of separately using the Key/Item builders +// to build the list as a List of Structs rather than building the keys/items +// separately. +func (b *MapBuilder) ValueBuilder() Builder { + return b.listBuilder.ValueBuilder() +} + +func (b *MapBuilder) AppendValueFromString(s string) error { + return b.listBuilder.AppendValueFromString(s) +} + +func (b *MapBuilder) UnmarshalOne(dec *json.Decoder) error { + return b.listBuilder.UnmarshalOne(dec) +} + +func (b *MapBuilder) Unmarshal(dec *json.Decoder) error { + return b.listBuilder.Unmarshal(dec) +} + +func (b *MapBuilder) UnmarshalJSON(data []byte) error { + dec := json.NewDecoder(bytes.NewReader(data)) + t, err := dec.Token() + if err != nil { + return err + } + + if delim, ok := t.(json.Delim); !ok || delim != '[' { + return fmt.Errorf("map builder must unpack from json array, found %s", delim) + } + + return b.Unmarshal(dec) +} + +var ( + _ arrow.Array = (*Map)(nil) + _ Builder = (*MapBuilder)(nil) + _ ListLikeBuilder = (*MapBuilder)(nil) +) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array/null.go b/vendor/github.com/apache/arrow/go/v14/arrow/array/null.go new file mode 100644 index 000000000..150a1030e --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array/null.go @@ -0,0 +1,218 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package array + +import ( + "bytes" + "fmt" + "reflect" + "strings" + "sync/atomic" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/internal/debug" + "github.com/apache/arrow/go/v14/arrow/memory" + "github.com/apache/arrow/go/v14/internal/json" +) + +// Null represents an immutable, degenerate array with no physical storage. +type Null struct { + array +} + +// NewNull returns a new Null array value of size n. +func NewNull(n int) *Null { + a := &Null{} + a.refCount = 1 + data := NewData( + arrow.Null, n, + []*memory.Buffer{nil}, + nil, + n, + 0, + ) + a.setData(data) + data.Release() + return a +} + +// NewNullData returns a new Null array value, from data. +func NewNullData(data arrow.ArrayData) *Null { + a := &Null{} + a.refCount = 1 + a.setData(data.(*Data)) + return a +} + +func (a *Null) ValueStr(int) string { return NullValueStr } + +func (a *Null) Value(int) interface{} { return nil } + +func (a *Null) String() string { + o := new(strings.Builder) + o.WriteString("[") + for i := 0; i < a.Len(); i++ { + if i > 0 { + o.WriteString(" ") + } + o.WriteString(NullValueStr) + } + o.WriteString("]") + return o.String() +} + +func (a *Null) setData(data *Data) { + a.array.setData(data) + a.array.nullBitmapBytes = nil + a.array.data.nulls = a.array.data.length +} + +func (a *Null) GetOneForMarshal(i int) interface{} { + return nil +} + +func (a *Null) MarshalJSON() ([]byte, error) { + return json.Marshal(make([]interface{}, a.Len())) +} + +type NullBuilder struct { + builder +} + +// NewNullBuilder returns a builder, using the provided memory allocator. +func NewNullBuilder(mem memory.Allocator) *NullBuilder { + return &NullBuilder{builder: builder{refCount: 1, mem: mem}} +} + +func (b *NullBuilder) Type() arrow.DataType { return arrow.Null } + +// Release decreases the reference count by 1. +// When the reference count goes to zero, the memory is freed. +func (b *NullBuilder) Release() { + debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases") + + if atomic.AddInt64(&b.refCount, -1) == 0 { + if b.nullBitmap != nil { + b.nullBitmap.Release() + b.nullBitmap = nil + } + } +} + +func (b *NullBuilder) AppendNull() { + b.builder.length++ + b.builder.nulls++ +} + +func (b *NullBuilder) AppendNulls(n int) { + for i := 0; i < n; i++ { + b.AppendNull() + } +} + +func (b *NullBuilder) AppendValueFromString(s string) error { + if s == NullValueStr { + b.AppendNull() + return nil + } + return fmt.Errorf("cannot convert %q to null", s) +} + +func (b *NullBuilder) AppendEmptyValue() { b.AppendNull() } + +func (b *NullBuilder) AppendEmptyValues(n int) { b.AppendNulls(n) } + +func (*NullBuilder) Reserve(size int) {} +func (*NullBuilder) Resize(size int) {} + +func (*NullBuilder) init(cap int) {} +func (*NullBuilder) resize(newBits int, init func(int)) {} + +// NewArray creates a Null array from the memory buffers used by the builder and resets the NullBuilder +// so it can be used to build a new array. +func (b *NullBuilder) NewArray() arrow.Array { + return b.NewNullArray() +} + +// NewNullArray creates a Null array from the memory buffers used by the builder and resets the NullBuilder +// so it can be used to build a new array. +func (b *NullBuilder) NewNullArray() (a *Null) { + data := b.newData() + a = NewNullData(data) + data.Release() + return +} + +func (b *NullBuilder) newData() (data *Data) { + data = NewData( + arrow.Null, b.length, + []*memory.Buffer{nil}, + nil, + b.nulls, + 0, + ) + b.reset() + + return +} + +func (b *NullBuilder) UnmarshalOne(dec *json.Decoder) error { + t, err := dec.Token() + if err != nil { + return err + } + + switch t.(type) { + case nil: + b.AppendNull() + default: + return &json.UnmarshalTypeError{ + Value: fmt.Sprint(t), + Type: reflect.TypeOf(nil), + Offset: dec.InputOffset(), + } + } + return nil +} + +func (b *NullBuilder) Unmarshal(dec *json.Decoder) error { + for dec.More() { + if err := b.UnmarshalOne(dec); err != nil { + return err + } + } + return nil +} + +func (b *NullBuilder) UnmarshalJSON(data []byte) error { + dec := json.NewDecoder(bytes.NewReader(data)) + t, err := dec.Token() + if err != nil { + return err + } + + if delim, ok := t.(json.Delim); !ok || delim != '[' { + return fmt.Errorf("null builder must unpack from json array, found %s", delim) + } + + return b.Unmarshal(dec) +} + +var ( + _ arrow.Array = (*Null)(nil) + _ Builder = (*NullBuilder)(nil) +) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array/numeric.gen.go b/vendor/github.com/apache/arrow/go/v14/arrow/array/numeric.gen.go new file mode 100644 index 000000000..a3e110151 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array/numeric.gen.go @@ -0,0 +1,1430 @@ +// Code generated by array/numeric.gen.go.tmpl. DO NOT EDIT. + +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package array + +import ( + "fmt" + "strconv" + "strings" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/internal/json" +) + +// A type which represents an immutable sequence of int64 values. +type Int64 struct { + array + values []int64 +} + +// NewInt64Data creates a new Int64. +func NewInt64Data(data arrow.ArrayData) *Int64 { + a := &Int64{} + a.refCount = 1 + a.setData(data.(*Data)) + return a +} + +// Reset resets the array for re-use. +func (a *Int64) Reset(data *Data) { + a.setData(data) +} + +// Value returns the value at the specified index. +func (a *Int64) Value(i int) int64 { return a.values[i] } + +// Values returns the values. +func (a *Int64) Int64Values() []int64 { return a.values } + +// String returns a string representation of the array. +func (a *Int64) String() string { + o := new(strings.Builder) + o.WriteString("[") + for i, v := range a.values { + if i > 0 { + fmt.Fprintf(o, " ") + } + switch { + case a.IsNull(i): + o.WriteString(NullValueStr) + default: + fmt.Fprintf(o, "%v", v) + } + } + o.WriteString("]") + return o.String() +} + +func (a *Int64) setData(data *Data) { + a.array.setData(data) + vals := data.buffers[1] + if vals != nil { + a.values = arrow.Int64Traits.CastFromBytes(vals.Bytes()) + beg := a.array.data.offset + end := beg + a.array.data.length + a.values = a.values[beg:end] + } +} + +func (a *Int64) ValueStr(i int) string { + if a.IsNull(i) { + return NullValueStr + } + return strconv.FormatInt(int64(a.Value(i)), 10) +} + +func (a *Int64) GetOneForMarshal(i int) interface{} { + if a.IsNull(i) { + return nil + } + + return a.values[i] +} + +func (a *Int64) MarshalJSON() ([]byte, error) { + vals := make([]interface{}, a.Len()) + for i := 0; i < a.Len(); i++ { + if a.IsValid(i) { + vals[i] = a.values[i] + } else { + vals[i] = nil + } + } + + return json.Marshal(vals) +} + +func arrayEqualInt64(left, right *Int64) bool { + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + if left.Value(i) != right.Value(i) { + return false + } + } + return true +} + +// A type which represents an immutable sequence of uint64 values. +type Uint64 struct { + array + values []uint64 +} + +// NewUint64Data creates a new Uint64. +func NewUint64Data(data arrow.ArrayData) *Uint64 { + a := &Uint64{} + a.refCount = 1 + a.setData(data.(*Data)) + return a +} + +// Reset resets the array for re-use. +func (a *Uint64) Reset(data *Data) { + a.setData(data) +} + +// Value returns the value at the specified index. +func (a *Uint64) Value(i int) uint64 { return a.values[i] } + +// Values returns the values. +func (a *Uint64) Uint64Values() []uint64 { return a.values } + +// String returns a string representation of the array. +func (a *Uint64) String() string { + o := new(strings.Builder) + o.WriteString("[") + for i, v := range a.values { + if i > 0 { + fmt.Fprintf(o, " ") + } + switch { + case a.IsNull(i): + o.WriteString(NullValueStr) + default: + fmt.Fprintf(o, "%v", v) + } + } + o.WriteString("]") + return o.String() +} + +func (a *Uint64) setData(data *Data) { + a.array.setData(data) + vals := data.buffers[1] + if vals != nil { + a.values = arrow.Uint64Traits.CastFromBytes(vals.Bytes()) + beg := a.array.data.offset + end := beg + a.array.data.length + a.values = a.values[beg:end] + } +} + +func (a *Uint64) ValueStr(i int) string { + if a.IsNull(i) { + return NullValueStr + } + return strconv.FormatUint(uint64(a.Value(i)), 10) +} + +func (a *Uint64) GetOneForMarshal(i int) interface{} { + if a.IsNull(i) { + return nil + } + + return a.values[i] +} + +func (a *Uint64) MarshalJSON() ([]byte, error) { + vals := make([]interface{}, a.Len()) + for i := 0; i < a.Len(); i++ { + if a.IsValid(i) { + vals[i] = a.values[i] + } else { + vals[i] = nil + } + } + + return json.Marshal(vals) +} + +func arrayEqualUint64(left, right *Uint64) bool { + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + if left.Value(i) != right.Value(i) { + return false + } + } + return true +} + +// A type which represents an immutable sequence of float64 values. +type Float64 struct { + array + values []float64 +} + +// NewFloat64Data creates a new Float64. +func NewFloat64Data(data arrow.ArrayData) *Float64 { + a := &Float64{} + a.refCount = 1 + a.setData(data.(*Data)) + return a +} + +// Reset resets the array for re-use. +func (a *Float64) Reset(data *Data) { + a.setData(data) +} + +// Value returns the value at the specified index. +func (a *Float64) Value(i int) float64 { return a.values[i] } + +// Values returns the values. +func (a *Float64) Float64Values() []float64 { return a.values } + +// String returns a string representation of the array. +func (a *Float64) String() string { + o := new(strings.Builder) + o.WriteString("[") + for i, v := range a.values { + if i > 0 { + fmt.Fprintf(o, " ") + } + switch { + case a.IsNull(i): + o.WriteString(NullValueStr) + default: + fmt.Fprintf(o, "%v", v) + } + } + o.WriteString("]") + return o.String() +} + +func (a *Float64) setData(data *Data) { + a.array.setData(data) + vals := data.buffers[1] + if vals != nil { + a.values = arrow.Float64Traits.CastFromBytes(vals.Bytes()) + beg := a.array.data.offset + end := beg + a.array.data.length + a.values = a.values[beg:end] + } +} + +func (a *Float64) ValueStr(i int) string { + if a.IsNull(i) { + return NullValueStr + } + return strconv.FormatFloat(float64(a.Value(i)), 'g', -1, 64) +} + +func (a *Float64) GetOneForMarshal(i int) interface{} { + if a.IsNull(i) { + return nil + } + + return a.values[i] +} + +func (a *Float64) MarshalJSON() ([]byte, error) { + vals := make([]interface{}, a.Len()) + for i := 0; i < a.Len(); i++ { + if a.IsValid(i) { + vals[i] = a.values[i] + } else { + vals[i] = nil + } + } + + return json.Marshal(vals) +} + +func arrayEqualFloat64(left, right *Float64) bool { + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + if left.Value(i) != right.Value(i) { + return false + } + } + return true +} + +// A type which represents an immutable sequence of int32 values. +type Int32 struct { + array + values []int32 +} + +// NewInt32Data creates a new Int32. +func NewInt32Data(data arrow.ArrayData) *Int32 { + a := &Int32{} + a.refCount = 1 + a.setData(data.(*Data)) + return a +} + +// Reset resets the array for re-use. +func (a *Int32) Reset(data *Data) { + a.setData(data) +} + +// Value returns the value at the specified index. +func (a *Int32) Value(i int) int32 { return a.values[i] } + +// Values returns the values. +func (a *Int32) Int32Values() []int32 { return a.values } + +// String returns a string representation of the array. +func (a *Int32) String() string { + o := new(strings.Builder) + o.WriteString("[") + for i, v := range a.values { + if i > 0 { + fmt.Fprintf(o, " ") + } + switch { + case a.IsNull(i): + o.WriteString(NullValueStr) + default: + fmt.Fprintf(o, "%v", v) + } + } + o.WriteString("]") + return o.String() +} + +func (a *Int32) setData(data *Data) { + a.array.setData(data) + vals := data.buffers[1] + if vals != nil { + a.values = arrow.Int32Traits.CastFromBytes(vals.Bytes()) + beg := a.array.data.offset + end := beg + a.array.data.length + a.values = a.values[beg:end] + } +} + +func (a *Int32) ValueStr(i int) string { + if a.IsNull(i) { + return NullValueStr + } + return strconv.FormatInt(int64(a.Value(i)), 10) +} + +func (a *Int32) GetOneForMarshal(i int) interface{} { + if a.IsNull(i) { + return nil + } + + return a.values[i] +} + +func (a *Int32) MarshalJSON() ([]byte, error) { + vals := make([]interface{}, a.Len()) + for i := 0; i < a.Len(); i++ { + if a.IsValid(i) { + vals[i] = a.values[i] + } else { + vals[i] = nil + } + } + + return json.Marshal(vals) +} + +func arrayEqualInt32(left, right *Int32) bool { + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + if left.Value(i) != right.Value(i) { + return false + } + } + return true +} + +// A type which represents an immutable sequence of uint32 values. +type Uint32 struct { + array + values []uint32 +} + +// NewUint32Data creates a new Uint32. +func NewUint32Data(data arrow.ArrayData) *Uint32 { + a := &Uint32{} + a.refCount = 1 + a.setData(data.(*Data)) + return a +} + +// Reset resets the array for re-use. +func (a *Uint32) Reset(data *Data) { + a.setData(data) +} + +// Value returns the value at the specified index. +func (a *Uint32) Value(i int) uint32 { return a.values[i] } + +// Values returns the values. +func (a *Uint32) Uint32Values() []uint32 { return a.values } + +// String returns a string representation of the array. +func (a *Uint32) String() string { + o := new(strings.Builder) + o.WriteString("[") + for i, v := range a.values { + if i > 0 { + fmt.Fprintf(o, " ") + } + switch { + case a.IsNull(i): + o.WriteString(NullValueStr) + default: + fmt.Fprintf(o, "%v", v) + } + } + o.WriteString("]") + return o.String() +} + +func (a *Uint32) setData(data *Data) { + a.array.setData(data) + vals := data.buffers[1] + if vals != nil { + a.values = arrow.Uint32Traits.CastFromBytes(vals.Bytes()) + beg := a.array.data.offset + end := beg + a.array.data.length + a.values = a.values[beg:end] + } +} + +func (a *Uint32) ValueStr(i int) string { + if a.IsNull(i) { + return NullValueStr + } + return strconv.FormatUint(uint64(a.Value(i)), 10) +} + +func (a *Uint32) GetOneForMarshal(i int) interface{} { + if a.IsNull(i) { + return nil + } + + return a.values[i] +} + +func (a *Uint32) MarshalJSON() ([]byte, error) { + vals := make([]interface{}, a.Len()) + for i := 0; i < a.Len(); i++ { + if a.IsValid(i) { + vals[i] = a.values[i] + } else { + vals[i] = nil + } + } + + return json.Marshal(vals) +} + +func arrayEqualUint32(left, right *Uint32) bool { + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + if left.Value(i) != right.Value(i) { + return false + } + } + return true +} + +// A type which represents an immutable sequence of float32 values. +type Float32 struct { + array + values []float32 +} + +// NewFloat32Data creates a new Float32. +func NewFloat32Data(data arrow.ArrayData) *Float32 { + a := &Float32{} + a.refCount = 1 + a.setData(data.(*Data)) + return a +} + +// Reset resets the array for re-use. +func (a *Float32) Reset(data *Data) { + a.setData(data) +} + +// Value returns the value at the specified index. +func (a *Float32) Value(i int) float32 { return a.values[i] } + +// Values returns the values. +func (a *Float32) Float32Values() []float32 { return a.values } + +// String returns a string representation of the array. +func (a *Float32) String() string { + o := new(strings.Builder) + o.WriteString("[") + for i, v := range a.values { + if i > 0 { + fmt.Fprintf(o, " ") + } + switch { + case a.IsNull(i): + o.WriteString(NullValueStr) + default: + fmt.Fprintf(o, "%v", v) + } + } + o.WriteString("]") + return o.String() +} + +func (a *Float32) setData(data *Data) { + a.array.setData(data) + vals := data.buffers[1] + if vals != nil { + a.values = arrow.Float32Traits.CastFromBytes(vals.Bytes()) + beg := a.array.data.offset + end := beg + a.array.data.length + a.values = a.values[beg:end] + } +} + +func (a *Float32) ValueStr(i int) string { + if a.IsNull(i) { + return NullValueStr + } + return strconv.FormatFloat(float64(a.Value(i)), 'g', -1, 32) +} + +func (a *Float32) GetOneForMarshal(i int) interface{} { + if a.IsNull(i) { + return nil + } + + return a.values[i] +} + +func (a *Float32) MarshalJSON() ([]byte, error) { + vals := make([]interface{}, a.Len()) + for i := 0; i < a.Len(); i++ { + if a.IsValid(i) { + vals[i] = a.values[i] + } else { + vals[i] = nil + } + } + + return json.Marshal(vals) +} + +func arrayEqualFloat32(left, right *Float32) bool { + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + if left.Value(i) != right.Value(i) { + return false + } + } + return true +} + +// A type which represents an immutable sequence of int16 values. +type Int16 struct { + array + values []int16 +} + +// NewInt16Data creates a new Int16. +func NewInt16Data(data arrow.ArrayData) *Int16 { + a := &Int16{} + a.refCount = 1 + a.setData(data.(*Data)) + return a +} + +// Reset resets the array for re-use. +func (a *Int16) Reset(data *Data) { + a.setData(data) +} + +// Value returns the value at the specified index. +func (a *Int16) Value(i int) int16 { return a.values[i] } + +// Values returns the values. +func (a *Int16) Int16Values() []int16 { return a.values } + +// String returns a string representation of the array. +func (a *Int16) String() string { + o := new(strings.Builder) + o.WriteString("[") + for i, v := range a.values { + if i > 0 { + fmt.Fprintf(o, " ") + } + switch { + case a.IsNull(i): + o.WriteString(NullValueStr) + default: + fmt.Fprintf(o, "%v", v) + } + } + o.WriteString("]") + return o.String() +} + +func (a *Int16) setData(data *Data) { + a.array.setData(data) + vals := data.buffers[1] + if vals != nil { + a.values = arrow.Int16Traits.CastFromBytes(vals.Bytes()) + beg := a.array.data.offset + end := beg + a.array.data.length + a.values = a.values[beg:end] + } +} + +func (a *Int16) ValueStr(i int) string { + if a.IsNull(i) { + return NullValueStr + } + return strconv.FormatInt(int64(a.Value(i)), 10) +} + +func (a *Int16) GetOneForMarshal(i int) interface{} { + if a.IsNull(i) { + return nil + } + + return a.values[i] +} + +func (a *Int16) MarshalJSON() ([]byte, error) { + vals := make([]interface{}, a.Len()) + for i := 0; i < a.Len(); i++ { + if a.IsValid(i) { + vals[i] = a.values[i] + } else { + vals[i] = nil + } + } + + return json.Marshal(vals) +} + +func arrayEqualInt16(left, right *Int16) bool { + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + if left.Value(i) != right.Value(i) { + return false + } + } + return true +} + +// A type which represents an immutable sequence of uint16 values. +type Uint16 struct { + array + values []uint16 +} + +// NewUint16Data creates a new Uint16. +func NewUint16Data(data arrow.ArrayData) *Uint16 { + a := &Uint16{} + a.refCount = 1 + a.setData(data.(*Data)) + return a +} + +// Reset resets the array for re-use. +func (a *Uint16) Reset(data *Data) { + a.setData(data) +} + +// Value returns the value at the specified index. +func (a *Uint16) Value(i int) uint16 { return a.values[i] } + +// Values returns the values. +func (a *Uint16) Uint16Values() []uint16 { return a.values } + +// String returns a string representation of the array. +func (a *Uint16) String() string { + o := new(strings.Builder) + o.WriteString("[") + for i, v := range a.values { + if i > 0 { + fmt.Fprintf(o, " ") + } + switch { + case a.IsNull(i): + o.WriteString(NullValueStr) + default: + fmt.Fprintf(o, "%v", v) + } + } + o.WriteString("]") + return o.String() +} + +func (a *Uint16) setData(data *Data) { + a.array.setData(data) + vals := data.buffers[1] + if vals != nil { + a.values = arrow.Uint16Traits.CastFromBytes(vals.Bytes()) + beg := a.array.data.offset + end := beg + a.array.data.length + a.values = a.values[beg:end] + } +} + +func (a *Uint16) ValueStr(i int) string { + if a.IsNull(i) { + return NullValueStr + } + return strconv.FormatUint(uint64(a.Value(i)), 10) +} + +func (a *Uint16) GetOneForMarshal(i int) interface{} { + if a.IsNull(i) { + return nil + } + + return a.values[i] +} + +func (a *Uint16) MarshalJSON() ([]byte, error) { + vals := make([]interface{}, a.Len()) + for i := 0; i < a.Len(); i++ { + if a.IsValid(i) { + vals[i] = a.values[i] + } else { + vals[i] = nil + } + } + + return json.Marshal(vals) +} + +func arrayEqualUint16(left, right *Uint16) bool { + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + if left.Value(i) != right.Value(i) { + return false + } + } + return true +} + +// A type which represents an immutable sequence of int8 values. +type Int8 struct { + array + values []int8 +} + +// NewInt8Data creates a new Int8. +func NewInt8Data(data arrow.ArrayData) *Int8 { + a := &Int8{} + a.refCount = 1 + a.setData(data.(*Data)) + return a +} + +// Reset resets the array for re-use. +func (a *Int8) Reset(data *Data) { + a.setData(data) +} + +// Value returns the value at the specified index. +func (a *Int8) Value(i int) int8 { return a.values[i] } + +// Values returns the values. +func (a *Int8) Int8Values() []int8 { return a.values } + +// String returns a string representation of the array. +func (a *Int8) String() string { + o := new(strings.Builder) + o.WriteString("[") + for i, v := range a.values { + if i > 0 { + fmt.Fprintf(o, " ") + } + switch { + case a.IsNull(i): + o.WriteString(NullValueStr) + default: + fmt.Fprintf(o, "%v", v) + } + } + o.WriteString("]") + return o.String() +} + +func (a *Int8) setData(data *Data) { + a.array.setData(data) + vals := data.buffers[1] + if vals != nil { + a.values = arrow.Int8Traits.CastFromBytes(vals.Bytes()) + beg := a.array.data.offset + end := beg + a.array.data.length + a.values = a.values[beg:end] + } +} + +func (a *Int8) ValueStr(i int) string { + if a.IsNull(i) { + return NullValueStr + } + return strconv.FormatInt(int64(a.Value(i)), 10) +} + +func (a *Int8) GetOneForMarshal(i int) interface{} { + if a.IsNull(i) { + return nil + } + + return float64(a.values[i]) // prevent uint8 from being seen as binary data +} + +func (a *Int8) MarshalJSON() ([]byte, error) { + vals := make([]interface{}, a.Len()) + for i := 0; i < a.Len(); i++ { + if a.IsValid(i) { + vals[i] = float64(a.values[i]) // prevent uint8 from being seen as binary data + } else { + vals[i] = nil + } + } + + return json.Marshal(vals) +} + +func arrayEqualInt8(left, right *Int8) bool { + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + if left.Value(i) != right.Value(i) { + return false + } + } + return true +} + +// A type which represents an immutable sequence of uint8 values. +type Uint8 struct { + array + values []uint8 +} + +// NewUint8Data creates a new Uint8. +func NewUint8Data(data arrow.ArrayData) *Uint8 { + a := &Uint8{} + a.refCount = 1 + a.setData(data.(*Data)) + return a +} + +// Reset resets the array for re-use. +func (a *Uint8) Reset(data *Data) { + a.setData(data) +} + +// Value returns the value at the specified index. +func (a *Uint8) Value(i int) uint8 { return a.values[i] } + +// Values returns the values. +func (a *Uint8) Uint8Values() []uint8 { return a.values } + +// String returns a string representation of the array. +func (a *Uint8) String() string { + o := new(strings.Builder) + o.WriteString("[") + for i, v := range a.values { + if i > 0 { + fmt.Fprintf(o, " ") + } + switch { + case a.IsNull(i): + o.WriteString(NullValueStr) + default: + fmt.Fprintf(o, "%v", v) + } + } + o.WriteString("]") + return o.String() +} + +func (a *Uint8) setData(data *Data) { + a.array.setData(data) + vals := data.buffers[1] + if vals != nil { + a.values = arrow.Uint8Traits.CastFromBytes(vals.Bytes()) + beg := a.array.data.offset + end := beg + a.array.data.length + a.values = a.values[beg:end] + } +} + +func (a *Uint8) ValueStr(i int) string { + if a.IsNull(i) { + return NullValueStr + } + return strconv.FormatUint(uint64(a.Value(i)), 10) +} + +func (a *Uint8) GetOneForMarshal(i int) interface{} { + if a.IsNull(i) { + return nil + } + + return float64(a.values[i]) // prevent uint8 from being seen as binary data +} + +func (a *Uint8) MarshalJSON() ([]byte, error) { + vals := make([]interface{}, a.Len()) + for i := 0; i < a.Len(); i++ { + if a.IsValid(i) { + vals[i] = float64(a.values[i]) // prevent uint8 from being seen as binary data + } else { + vals[i] = nil + } + } + + return json.Marshal(vals) +} + +func arrayEqualUint8(left, right *Uint8) bool { + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + if left.Value(i) != right.Value(i) { + return false + } + } + return true +} + +// A type which represents an immutable sequence of arrow.Time32 values. +type Time32 struct { + array + values []arrow.Time32 +} + +// NewTime32Data creates a new Time32. +func NewTime32Data(data arrow.ArrayData) *Time32 { + a := &Time32{} + a.refCount = 1 + a.setData(data.(*Data)) + return a +} + +// Reset resets the array for re-use. +func (a *Time32) Reset(data *Data) { + a.setData(data) +} + +// Value returns the value at the specified index. +func (a *Time32) Value(i int) arrow.Time32 { return a.values[i] } + +// Values returns the values. +func (a *Time32) Time32Values() []arrow.Time32 { return a.values } + +// String returns a string representation of the array. +func (a *Time32) String() string { + o := new(strings.Builder) + o.WriteString("[") + for i, v := range a.values { + if i > 0 { + fmt.Fprintf(o, " ") + } + switch { + case a.IsNull(i): + o.WriteString(NullValueStr) + default: + fmt.Fprintf(o, "%v", v) + } + } + o.WriteString("]") + return o.String() +} + +func (a *Time32) setData(data *Data) { + a.array.setData(data) + vals := data.buffers[1] + if vals != nil { + a.values = arrow.Time32Traits.CastFromBytes(vals.Bytes()) + beg := a.array.data.offset + end := beg + a.array.data.length + a.values = a.values[beg:end] + } +} + +func (a *Time32) ValueStr(i int) string { + if a.IsNull(i) { + return NullValueStr + } + return a.values[i].FormattedString(a.DataType().(*arrow.Time32Type).Unit) +} + +func (a *Time32) GetOneForMarshal(i int) interface{} { + if a.IsNull(i) { + return nil + } + return a.values[i].ToTime(a.DataType().(*arrow.Time32Type).Unit).Format("15:04:05.999999999") +} + +func (a *Time32) MarshalJSON() ([]byte, error) { + vals := make([]interface{}, a.Len()) + for i := range a.values { + vals[i] = a.GetOneForMarshal(i) + } + + return json.Marshal(vals) +} + +func arrayEqualTime32(left, right *Time32) bool { + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + if left.Value(i) != right.Value(i) { + return false + } + } + return true +} + +// A type which represents an immutable sequence of arrow.Time64 values. +type Time64 struct { + array + values []arrow.Time64 +} + +// NewTime64Data creates a new Time64. +func NewTime64Data(data arrow.ArrayData) *Time64 { + a := &Time64{} + a.refCount = 1 + a.setData(data.(*Data)) + return a +} + +// Reset resets the array for re-use. +func (a *Time64) Reset(data *Data) { + a.setData(data) +} + +// Value returns the value at the specified index. +func (a *Time64) Value(i int) arrow.Time64 { return a.values[i] } + +// Values returns the values. +func (a *Time64) Time64Values() []arrow.Time64 { return a.values } + +// String returns a string representation of the array. +func (a *Time64) String() string { + o := new(strings.Builder) + o.WriteString("[") + for i, v := range a.values { + if i > 0 { + fmt.Fprintf(o, " ") + } + switch { + case a.IsNull(i): + o.WriteString(NullValueStr) + default: + fmt.Fprintf(o, "%v", v) + } + } + o.WriteString("]") + return o.String() +} + +func (a *Time64) setData(data *Data) { + a.array.setData(data) + vals := data.buffers[1] + if vals != nil { + a.values = arrow.Time64Traits.CastFromBytes(vals.Bytes()) + beg := a.array.data.offset + end := beg + a.array.data.length + a.values = a.values[beg:end] + } +} + +func (a *Time64) ValueStr(i int) string { + if a.IsNull(i) { + return NullValueStr + } + return a.values[i].FormattedString(a.DataType().(*arrow.Time64Type).Unit) +} + +func (a *Time64) GetOneForMarshal(i int) interface{} { + if a.IsNull(i) { + return nil + } + return a.values[i].ToTime(a.DataType().(*arrow.Time64Type).Unit).Format("15:04:05.999999999") +} + +func (a *Time64) MarshalJSON() ([]byte, error) { + vals := make([]interface{}, a.Len()) + for i := range a.values { + vals[i] = a.GetOneForMarshal(i) + } + + return json.Marshal(vals) +} + +func arrayEqualTime64(left, right *Time64) bool { + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + if left.Value(i) != right.Value(i) { + return false + } + } + return true +} + +// A type which represents an immutable sequence of arrow.Date32 values. +type Date32 struct { + array + values []arrow.Date32 +} + +// NewDate32Data creates a new Date32. +func NewDate32Data(data arrow.ArrayData) *Date32 { + a := &Date32{} + a.refCount = 1 + a.setData(data.(*Data)) + return a +} + +// Reset resets the array for re-use. +func (a *Date32) Reset(data *Data) { + a.setData(data) +} + +// Value returns the value at the specified index. +func (a *Date32) Value(i int) arrow.Date32 { return a.values[i] } + +// Values returns the values. +func (a *Date32) Date32Values() []arrow.Date32 { return a.values } + +// String returns a string representation of the array. +func (a *Date32) String() string { + o := new(strings.Builder) + o.WriteString("[") + for i, v := range a.values { + if i > 0 { + fmt.Fprintf(o, " ") + } + switch { + case a.IsNull(i): + o.WriteString(NullValueStr) + default: + fmt.Fprintf(o, "%v", v) + } + } + o.WriteString("]") + return o.String() +} + +func (a *Date32) setData(data *Data) { + a.array.setData(data) + vals := data.buffers[1] + if vals != nil { + a.values = arrow.Date32Traits.CastFromBytes(vals.Bytes()) + beg := a.array.data.offset + end := beg + a.array.data.length + a.values = a.values[beg:end] + } +} + +func (a *Date32) ValueStr(i int) string { + if a.IsNull(i) { + return NullValueStr + } + return a.values[i].FormattedString() +} + +func (a *Date32) GetOneForMarshal(i int) interface{} { + if a.IsNull(i) { + return nil + } + return a.values[i].ToTime().Format("2006-01-02") +} + +func (a *Date32) MarshalJSON() ([]byte, error) { + vals := make([]interface{}, a.Len()) + for i := range a.values { + vals[i] = a.GetOneForMarshal(i) + } + + return json.Marshal(vals) +} + +func arrayEqualDate32(left, right *Date32) bool { + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + if left.Value(i) != right.Value(i) { + return false + } + } + return true +} + +// A type which represents an immutable sequence of arrow.Date64 values. +type Date64 struct { + array + values []arrow.Date64 +} + +// NewDate64Data creates a new Date64. +func NewDate64Data(data arrow.ArrayData) *Date64 { + a := &Date64{} + a.refCount = 1 + a.setData(data.(*Data)) + return a +} + +// Reset resets the array for re-use. +func (a *Date64) Reset(data *Data) { + a.setData(data) +} + +// Value returns the value at the specified index. +func (a *Date64) Value(i int) arrow.Date64 { return a.values[i] } + +// Values returns the values. +func (a *Date64) Date64Values() []arrow.Date64 { return a.values } + +// String returns a string representation of the array. +func (a *Date64) String() string { + o := new(strings.Builder) + o.WriteString("[") + for i, v := range a.values { + if i > 0 { + fmt.Fprintf(o, " ") + } + switch { + case a.IsNull(i): + o.WriteString(NullValueStr) + default: + fmt.Fprintf(o, "%v", v) + } + } + o.WriteString("]") + return o.String() +} + +func (a *Date64) setData(data *Data) { + a.array.setData(data) + vals := data.buffers[1] + if vals != nil { + a.values = arrow.Date64Traits.CastFromBytes(vals.Bytes()) + beg := a.array.data.offset + end := beg + a.array.data.length + a.values = a.values[beg:end] + } +} + +func (a *Date64) ValueStr(i int) string { + if a.IsNull(i) { + return NullValueStr + } + return a.values[i].FormattedString() +} + +func (a *Date64) GetOneForMarshal(i int) interface{} { + if a.IsNull(i) { + return nil + } + return a.values[i].ToTime().Format("2006-01-02") +} + +func (a *Date64) MarshalJSON() ([]byte, error) { + vals := make([]interface{}, a.Len()) + for i := range a.values { + vals[i] = a.GetOneForMarshal(i) + } + + return json.Marshal(vals) +} + +func arrayEqualDate64(left, right *Date64) bool { + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + if left.Value(i) != right.Value(i) { + return false + } + } + return true +} + +// A type which represents an immutable sequence of arrow.Duration values. +type Duration struct { + array + values []arrow.Duration +} + +// NewDurationData creates a new Duration. +func NewDurationData(data arrow.ArrayData) *Duration { + a := &Duration{} + a.refCount = 1 + a.setData(data.(*Data)) + return a +} + +// Reset resets the array for re-use. +func (a *Duration) Reset(data *Data) { + a.setData(data) +} + +// Value returns the value at the specified index. +func (a *Duration) Value(i int) arrow.Duration { return a.values[i] } + +// Values returns the values. +func (a *Duration) DurationValues() []arrow.Duration { return a.values } + +// String returns a string representation of the array. +func (a *Duration) String() string { + o := new(strings.Builder) + o.WriteString("[") + for i, v := range a.values { + if i > 0 { + fmt.Fprintf(o, " ") + } + switch { + case a.IsNull(i): + o.WriteString(NullValueStr) + default: + fmt.Fprintf(o, "%v", v) + } + } + o.WriteString("]") + return o.String() +} + +func (a *Duration) setData(data *Data) { + a.array.setData(data) + vals := data.buffers[1] + if vals != nil { + a.values = arrow.DurationTraits.CastFromBytes(vals.Bytes()) + beg := a.array.data.offset + end := beg + a.array.data.length + a.values = a.values[beg:end] + } +} + +func (a *Duration) ValueStr(i int) string { + if a.IsNull(i) { + return NullValueStr + } + // return value and suffix as a string such as "12345ms" + return fmt.Sprintf("%d%s", a.values[i], a.DataType().(*arrow.DurationType).Unit) +} + +func (a *Duration) GetOneForMarshal(i int) interface{} { + if a.IsNull(i) { + return nil + } + // return value and suffix as a string such as "12345ms" + return fmt.Sprintf("%d%s", a.values[i], a.DataType().(*arrow.DurationType).Unit.String()) +} + +func (a *Duration) MarshalJSON() ([]byte, error) { + vals := make([]interface{}, a.Len()) + for i := range a.values { + vals[i] = a.GetOneForMarshal(i) + } + + return json.Marshal(vals) +} + +func arrayEqualDuration(left, right *Duration) bool { + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + if left.Value(i) != right.Value(i) { + return false + } + } + return true +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array/numeric.gen.go.tmpl b/vendor/github.com/apache/arrow/go/v14/arrow/array/numeric.gen.go.tmpl new file mode 100644 index 000000000..34d17fbfc --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array/numeric.gen.go.tmpl @@ -0,0 +1,158 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package array + +import ( + "fmt" + "strings" + "time" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/internal/json" +) + +{{range .In}} + +// A type which represents an immutable sequence of {{or .QualifiedType .Type}} values. +type {{.Name}} struct { + array + values []{{or .QualifiedType .Type}} +} + +// New{{.Name}}Data creates a new {{.Name}}. +func New{{.Name}}Data(data arrow.ArrayData) *{{.Name}} { + a := &{{.Name}}{} + a.refCount = 1 + a.setData(data.(*Data)) + return a +} + +// Reset resets the array for re-use. +func (a *{{.Name}}) Reset(data *Data) { + a.setData(data) +} + +// Value returns the value at the specified index. +func (a *{{.Name}}) Value(i int) {{or .QualifiedType .Type}} { return a.values[i] } + +// Values returns the values. +func (a *{{.Name}}) {{.Name}}Values() []{{or .QualifiedType .Type}} { return a.values } + +// String returns a string representation of the array. +func (a *{{.Name}}) String() string { + o := new(strings.Builder) + o.WriteString("[") + for i, v := range a.values { + if i > 0 { + fmt.Fprintf(o, " ") + } + switch { + case a.IsNull(i): + o.WriteString(NullValueStr) + default: + fmt.Fprintf(o, "%v", v) + } + } + o.WriteString("]") + return o.String() +} + +func (a *{{.Name}}) setData(data *Data) { + a.array.setData(data) + vals := data.buffers[1] + if vals != nil { + a.values = arrow.{{.Name}}Traits.CastFromBytes(vals.Bytes()) + beg := a.array.data.offset + end := beg + a.array.data.length + a.values = a.values[beg:end] + } +} + +func (a *{{.Name}}) ValueStr(i int) string { + if a.IsNull(i) { + return NullValueStr + } +{{if or (eq .Name "Date32") (eq .Name "Date64") -}} + return a.values[i].FormattedString() +{{else if or (eq .Name "Time32") (eq .Name "Time64") -}} + return a.values[i].FormattedString(a.DataType().(*{{.QualifiedType}}Type).Unit) +{{else if (eq .Name "Duration") -}} + // return value and suffix as a string such as "12345ms" + return fmt.Sprintf("%d%s", a.values[i], a.DataType().(*{{.QualifiedType}}Type).Unit) +{{else if or (eq .Name "Int8") (eq .Name "Int16") (eq .Name "Int32") (eq .Name "Int64") -}} + return strconv.FormatInt(int64(a.Value(i)), 10) +{{else if or (eq .Name "Uint8") (eq .Name "Uint16") (eq .Name "Uint32") (eq .Name "Uint64") -}} + return strconv.FormatUint(uint64(a.Value(i)), 10) +{{else if or (eq .Name "Float32") -}} + return strconv.FormatFloat(float64(a.Value(i)), 'g', -1, 32) +{{else if or (eq .Name "Float64") -}} + return strconv.FormatFloat(float64(a.Value(i)), 'g', -1, 64) +{{else}} + return fmt.Sprintf("%v", a.values[i]) +{{end -}} +} + +func (a *{{.Name}}) GetOneForMarshal(i int) interface{} { + if a.IsNull(i) { + return nil + } +{{if or (eq .Name "Date32") (eq .Name "Date64") -}} + return a.values[i].ToTime().Format("2006-01-02") +{{else if or (eq .Name "Time32") (eq .Name "Time64") -}} + return a.values[i].ToTime(a.DataType().(*{{.QualifiedType}}Type).Unit).Format("15:04:05.999999999") +{{else if (eq .Name "Duration") -}} + // return value and suffix as a string such as "12345ms" + return fmt.Sprintf("%d%s", a.values[i], a.DataType().(*{{.QualifiedType}}Type).Unit.String()) +{{else if (eq .Size "1")}} + return float64(a.values[i]) // prevent uint8 from being seen as binary data +{{else}} + return a.values[i] +{{end -}} +} + +func (a *{{.Name}}) MarshalJSON() ([]byte, error) { +{{if .QualifiedType -}} + vals := make([]interface{}, a.Len()) + for i := range a.values { + vals[i] = a.GetOneForMarshal(i) + } +{{else -}} + vals := make([]interface{}, a.Len()) + for i := 0; i < a.Len(); i++ { + if a.IsValid(i) { + {{ if (eq .Size "1") }}vals[i] = float64(a.values[i]) // prevent uint8 from being seen as binary data{{ else }}vals[i] = a.values[i]{{ end }} + } else { + vals[i] = nil + } + } +{{end}} + return json.Marshal(vals) +} + +func arrayEqual{{.Name}}(left, right *{{.Name}}) bool { + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + if left.Value(i) != right.Value(i) { + return false + } + } + return true +} + +{{end}} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array/numericbuilder.gen.go b/vendor/github.com/apache/arrow/go/v14/arrow/array/numericbuilder.gen.go new file mode 100644 index 000000000..7f01180f5 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array/numericbuilder.gen.go @@ -0,0 +1,3664 @@ +// Code generated by array/numericbuilder.gen.go.tmpl. DO NOT EDIT. + +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package array + +import ( + "bytes" + "fmt" + "reflect" + "strconv" + "strings" + "sync/atomic" + "time" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/bitutil" + "github.com/apache/arrow/go/v14/arrow/internal/debug" + "github.com/apache/arrow/go/v14/arrow/memory" + "github.com/apache/arrow/go/v14/internal/json" +) + +type Int64Builder struct { + builder + + data *memory.Buffer + rawData []int64 +} + +func NewInt64Builder(mem memory.Allocator) *Int64Builder { + return &Int64Builder{builder: builder{refCount: 1, mem: mem}} +} + +func (b *Int64Builder) Type() arrow.DataType { return arrow.PrimitiveTypes.Int64 } + +// Release decreases the reference count by 1. +// When the reference count goes to zero, the memory is freed. +func (b *Int64Builder) Release() { + debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases") + + if atomic.AddInt64(&b.refCount, -1) == 0 { + if b.nullBitmap != nil { + b.nullBitmap.Release() + b.nullBitmap = nil + } + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + } +} + +func (b *Int64Builder) Append(v int64) { + b.Reserve(1) + b.UnsafeAppend(v) +} + +func (b *Int64Builder) AppendNull() { + b.Reserve(1) + b.UnsafeAppendBoolToBitmap(false) +} + +func (b *Int64Builder) AppendNulls(n int) { + for i := 0; i < n; i++ { + b.AppendNull() + } +} + +func (b *Int64Builder) AppendEmptyValue() { + b.Append(0) +} + +func (b *Int64Builder) AppendEmptyValues(n int) { + for i := 0; i < n; i++ { + b.AppendEmptyValue() + } +} + +func (b *Int64Builder) UnsafeAppend(v int64) { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + b.rawData[b.length] = v + b.length++ +} + +func (b *Int64Builder) UnsafeAppendBoolToBitmap(isValid bool) { + if isValid { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + } else { + b.nulls++ + } + b.length++ +} + +// AppendValues will append the values in the v slice. The valid slice determines which values +// in v are valid (not null). The valid slice must either be empty or be equal in length to v. If empty, +// all values in v are appended and considered valid. +func (b *Int64Builder) AppendValues(v []int64, valid []bool) { + if len(v) != len(valid) && len(valid) != 0 { + panic("len(v) != len(valid) && len(valid) != 0") + } + + if len(v) == 0 { + return + } + + b.Reserve(len(v)) + arrow.Int64Traits.Copy(b.rawData[b.length:], v) + b.builder.unsafeAppendBoolsToBitmap(valid, len(v)) +} + +func (b *Int64Builder) init(capacity int) { + b.builder.init(capacity) + + b.data = memory.NewResizableBuffer(b.mem) + bytesN := arrow.Int64Traits.BytesRequired(capacity) + b.data.Resize(bytesN) + b.rawData = arrow.Int64Traits.CastFromBytes(b.data.Bytes()) +} + +// Reserve ensures there is enough space for appending n elements +// by checking the capacity and calling Resize if necessary. +func (b *Int64Builder) Reserve(n int) { + b.builder.reserve(n, b.Resize) +} + +// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(), +// additional memory will be allocated. If n is smaller, the allocated memory may reduced. +func (b *Int64Builder) Resize(n int) { + nBuilder := n + if n < minBuilderCapacity { + n = minBuilderCapacity + } + + if b.capacity == 0 { + b.init(n) + } else { + b.builder.resize(nBuilder, b.init) + b.data.Resize(arrow.Int64Traits.BytesRequired(n)) + b.rawData = arrow.Int64Traits.CastFromBytes(b.data.Bytes()) + } +} + +func (b *Int64Builder) Value(i int) int64 { + return b.rawData[i] +} + +// NewArray creates a Int64 array from the memory buffers used by the builder and resets the Int64Builder +// so it can be used to build a new array. +func (b *Int64Builder) NewArray() arrow.Array { + return b.NewInt64Array() +} + +// NewInt64Array creates a Int64 array from the memory buffers used by the builder and resets the Int64Builder +// so it can be used to build a new array. +func (b *Int64Builder) NewInt64Array() (a *Int64) { + data := b.newData() + a = NewInt64Data(data) + data.Release() + return +} + +func (b *Int64Builder) newData() (data *Data) { + bytesRequired := arrow.Int64Traits.BytesRequired(b.length) + if bytesRequired > 0 && bytesRequired < b.data.Len() { + // trim buffers + b.data.Resize(bytesRequired) + } + data = NewData(arrow.PrimitiveTypes.Int64, b.length, []*memory.Buffer{b.nullBitmap, b.data}, nil, b.nulls, 0) + b.reset() + + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + + return +} + +func (b *Int64Builder) AppendValueFromString(s string) error { + if s == NullValueStr { + b.AppendNull() + return nil + } + v, err := strconv.ParseInt(s, 10, 8*8) + if err != nil { + b.AppendNull() + return err + } + b.Append(int64(v)) + return nil +} + +func (b *Int64Builder) UnmarshalOne(dec *json.Decoder) error { + t, err := dec.Token() + if err != nil { + return err + } + + switch v := t.(type) { + case nil: + b.AppendNull() + + case string: + f, err := strconv.ParseInt(v, 10, 8*8) + if err != nil { + return &json.UnmarshalTypeError{ + Value: v, + Type: reflect.TypeOf(int64(0)), + Offset: dec.InputOffset(), + } + } + b.Append(int64(f)) + case float64: + b.Append(int64(v)) + case json.Number: + f, err := strconv.ParseInt(v.String(), 10, 8*8) + if err != nil { + return &json.UnmarshalTypeError{ + Value: v.String(), + Type: reflect.TypeOf(int64(0)), + Offset: dec.InputOffset(), + } + } + b.Append(int64(f)) + + default: + return &json.UnmarshalTypeError{ + Value: fmt.Sprint(t), + Type: reflect.TypeOf(int64(0)), + Offset: dec.InputOffset(), + } + } + + return nil +} + +func (b *Int64Builder) Unmarshal(dec *json.Decoder) error { + for dec.More() { + if err := b.UnmarshalOne(dec); err != nil { + return err + } + } + return nil +} + +func (b *Int64Builder) UnmarshalJSON(data []byte) error { + dec := json.NewDecoder(bytes.NewReader(data)) + t, err := dec.Token() + if err != nil { + return err + } + + if delim, ok := t.(json.Delim); !ok || delim != '[' { + return fmt.Errorf("binary builder must unpack from json array, found %s", delim) + } + + return b.Unmarshal(dec) +} + +type Uint64Builder struct { + builder + + data *memory.Buffer + rawData []uint64 +} + +func NewUint64Builder(mem memory.Allocator) *Uint64Builder { + return &Uint64Builder{builder: builder{refCount: 1, mem: mem}} +} + +func (b *Uint64Builder) Type() arrow.DataType { return arrow.PrimitiveTypes.Uint64 } + +// Release decreases the reference count by 1. +// When the reference count goes to zero, the memory is freed. +func (b *Uint64Builder) Release() { + debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases") + + if atomic.AddInt64(&b.refCount, -1) == 0 { + if b.nullBitmap != nil { + b.nullBitmap.Release() + b.nullBitmap = nil + } + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + } +} + +func (b *Uint64Builder) Append(v uint64) { + b.Reserve(1) + b.UnsafeAppend(v) +} + +func (b *Uint64Builder) AppendNull() { + b.Reserve(1) + b.UnsafeAppendBoolToBitmap(false) +} + +func (b *Uint64Builder) AppendNulls(n int) { + for i := 0; i < n; i++ { + b.AppendNull() + } +} + +func (b *Uint64Builder) AppendEmptyValue() { + b.Append(0) +} + +func (b *Uint64Builder) AppendEmptyValues(n int) { + for i := 0; i < n; i++ { + b.AppendEmptyValue() + } +} + +func (b *Uint64Builder) UnsafeAppend(v uint64) { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + b.rawData[b.length] = v + b.length++ +} + +func (b *Uint64Builder) UnsafeAppendBoolToBitmap(isValid bool) { + if isValid { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + } else { + b.nulls++ + } + b.length++ +} + +// AppendValues will append the values in the v slice. The valid slice determines which values +// in v are valid (not null). The valid slice must either be empty or be equal in length to v. If empty, +// all values in v are appended and considered valid. +func (b *Uint64Builder) AppendValues(v []uint64, valid []bool) { + if len(v) != len(valid) && len(valid) != 0 { + panic("len(v) != len(valid) && len(valid) != 0") + } + + if len(v) == 0 { + return + } + + b.Reserve(len(v)) + arrow.Uint64Traits.Copy(b.rawData[b.length:], v) + b.builder.unsafeAppendBoolsToBitmap(valid, len(v)) +} + +func (b *Uint64Builder) init(capacity int) { + b.builder.init(capacity) + + b.data = memory.NewResizableBuffer(b.mem) + bytesN := arrow.Uint64Traits.BytesRequired(capacity) + b.data.Resize(bytesN) + b.rawData = arrow.Uint64Traits.CastFromBytes(b.data.Bytes()) +} + +// Reserve ensures there is enough space for appending n elements +// by checking the capacity and calling Resize if necessary. +func (b *Uint64Builder) Reserve(n int) { + b.builder.reserve(n, b.Resize) +} + +// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(), +// additional memory will be allocated. If n is smaller, the allocated memory may reduced. +func (b *Uint64Builder) Resize(n int) { + nBuilder := n + if n < minBuilderCapacity { + n = minBuilderCapacity + } + + if b.capacity == 0 { + b.init(n) + } else { + b.builder.resize(nBuilder, b.init) + b.data.Resize(arrow.Uint64Traits.BytesRequired(n)) + b.rawData = arrow.Uint64Traits.CastFromBytes(b.data.Bytes()) + } +} + +func (b *Uint64Builder) Value(i int) uint64 { + return b.rawData[i] +} + +// NewArray creates a Uint64 array from the memory buffers used by the builder and resets the Uint64Builder +// so it can be used to build a new array. +func (b *Uint64Builder) NewArray() arrow.Array { + return b.NewUint64Array() +} + +// NewUint64Array creates a Uint64 array from the memory buffers used by the builder and resets the Uint64Builder +// so it can be used to build a new array. +func (b *Uint64Builder) NewUint64Array() (a *Uint64) { + data := b.newData() + a = NewUint64Data(data) + data.Release() + return +} + +func (b *Uint64Builder) newData() (data *Data) { + bytesRequired := arrow.Uint64Traits.BytesRequired(b.length) + if bytesRequired > 0 && bytesRequired < b.data.Len() { + // trim buffers + b.data.Resize(bytesRequired) + } + data = NewData(arrow.PrimitiveTypes.Uint64, b.length, []*memory.Buffer{b.nullBitmap, b.data}, nil, b.nulls, 0) + b.reset() + + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + + return +} + +func (b *Uint64Builder) AppendValueFromString(s string) error { + if s == NullValueStr { + b.AppendNull() + return nil + } + v, err := strconv.ParseUint(s, 10, 8*8) + if err != nil { + b.AppendNull() + return err + } + b.Append(uint64(v)) + return nil +} + +func (b *Uint64Builder) UnmarshalOne(dec *json.Decoder) error { + t, err := dec.Token() + if err != nil { + return err + } + + switch v := t.(type) { + case nil: + b.AppendNull() + + case string: + f, err := strconv.ParseUint(v, 10, 8*8) + if err != nil { + return &json.UnmarshalTypeError{ + Value: v, + Type: reflect.TypeOf(uint64(0)), + Offset: dec.InputOffset(), + } + } + b.Append(uint64(f)) + case float64: + b.Append(uint64(v)) + case json.Number: + f, err := strconv.ParseUint(v.String(), 10, 8*8) + if err != nil { + return &json.UnmarshalTypeError{ + Value: v.String(), + Type: reflect.TypeOf(uint64(0)), + Offset: dec.InputOffset(), + } + } + b.Append(uint64(f)) + + default: + return &json.UnmarshalTypeError{ + Value: fmt.Sprint(t), + Type: reflect.TypeOf(uint64(0)), + Offset: dec.InputOffset(), + } + } + + return nil +} + +func (b *Uint64Builder) Unmarshal(dec *json.Decoder) error { + for dec.More() { + if err := b.UnmarshalOne(dec); err != nil { + return err + } + } + return nil +} + +func (b *Uint64Builder) UnmarshalJSON(data []byte) error { + dec := json.NewDecoder(bytes.NewReader(data)) + t, err := dec.Token() + if err != nil { + return err + } + + if delim, ok := t.(json.Delim); !ok || delim != '[' { + return fmt.Errorf("binary builder must unpack from json array, found %s", delim) + } + + return b.Unmarshal(dec) +} + +type Float64Builder struct { + builder + + data *memory.Buffer + rawData []float64 +} + +func NewFloat64Builder(mem memory.Allocator) *Float64Builder { + return &Float64Builder{builder: builder{refCount: 1, mem: mem}} +} + +func (b *Float64Builder) Type() arrow.DataType { return arrow.PrimitiveTypes.Float64 } + +// Release decreases the reference count by 1. +// When the reference count goes to zero, the memory is freed. +func (b *Float64Builder) Release() { + debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases") + + if atomic.AddInt64(&b.refCount, -1) == 0 { + if b.nullBitmap != nil { + b.nullBitmap.Release() + b.nullBitmap = nil + } + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + } +} + +func (b *Float64Builder) Append(v float64) { + b.Reserve(1) + b.UnsafeAppend(v) +} + +func (b *Float64Builder) AppendNull() { + b.Reserve(1) + b.UnsafeAppendBoolToBitmap(false) +} + +func (b *Float64Builder) AppendNulls(n int) { + for i := 0; i < n; i++ { + b.AppendNull() + } +} + +func (b *Float64Builder) AppendEmptyValue() { + b.Append(0) +} + +func (b *Float64Builder) AppendEmptyValues(n int) { + for i := 0; i < n; i++ { + b.AppendEmptyValue() + } +} + +func (b *Float64Builder) UnsafeAppend(v float64) { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + b.rawData[b.length] = v + b.length++ +} + +func (b *Float64Builder) UnsafeAppendBoolToBitmap(isValid bool) { + if isValid { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + } else { + b.nulls++ + } + b.length++ +} + +// AppendValues will append the values in the v slice. The valid slice determines which values +// in v are valid (not null). The valid slice must either be empty or be equal in length to v. If empty, +// all values in v are appended and considered valid. +func (b *Float64Builder) AppendValues(v []float64, valid []bool) { + if len(v) != len(valid) && len(valid) != 0 { + panic("len(v) != len(valid) && len(valid) != 0") + } + + if len(v) == 0 { + return + } + + b.Reserve(len(v)) + arrow.Float64Traits.Copy(b.rawData[b.length:], v) + b.builder.unsafeAppendBoolsToBitmap(valid, len(v)) +} + +func (b *Float64Builder) init(capacity int) { + b.builder.init(capacity) + + b.data = memory.NewResizableBuffer(b.mem) + bytesN := arrow.Float64Traits.BytesRequired(capacity) + b.data.Resize(bytesN) + b.rawData = arrow.Float64Traits.CastFromBytes(b.data.Bytes()) +} + +// Reserve ensures there is enough space for appending n elements +// by checking the capacity and calling Resize if necessary. +func (b *Float64Builder) Reserve(n int) { + b.builder.reserve(n, b.Resize) +} + +// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(), +// additional memory will be allocated. If n is smaller, the allocated memory may reduced. +func (b *Float64Builder) Resize(n int) { + nBuilder := n + if n < minBuilderCapacity { + n = minBuilderCapacity + } + + if b.capacity == 0 { + b.init(n) + } else { + b.builder.resize(nBuilder, b.init) + b.data.Resize(arrow.Float64Traits.BytesRequired(n)) + b.rawData = arrow.Float64Traits.CastFromBytes(b.data.Bytes()) + } +} + +func (b *Float64Builder) Value(i int) float64 { + return b.rawData[i] +} + +// NewArray creates a Float64 array from the memory buffers used by the builder and resets the Float64Builder +// so it can be used to build a new array. +func (b *Float64Builder) NewArray() arrow.Array { + return b.NewFloat64Array() +} + +// NewFloat64Array creates a Float64 array from the memory buffers used by the builder and resets the Float64Builder +// so it can be used to build a new array. +func (b *Float64Builder) NewFloat64Array() (a *Float64) { + data := b.newData() + a = NewFloat64Data(data) + data.Release() + return +} + +func (b *Float64Builder) newData() (data *Data) { + bytesRequired := arrow.Float64Traits.BytesRequired(b.length) + if bytesRequired > 0 && bytesRequired < b.data.Len() { + // trim buffers + b.data.Resize(bytesRequired) + } + data = NewData(arrow.PrimitiveTypes.Float64, b.length, []*memory.Buffer{b.nullBitmap, b.data}, nil, b.nulls, 0) + b.reset() + + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + + return +} + +func (b *Float64Builder) AppendValueFromString(s string) error { + if s == NullValueStr { + b.AppendNull() + return nil + } + v, err := strconv.ParseFloat(s, 8*8) + if err != nil { + b.AppendNull() + return err + } + b.Append(float64(v)) + return nil +} + +func (b *Float64Builder) UnmarshalOne(dec *json.Decoder) error { + t, err := dec.Token() + if err != nil { + return err + } + + switch v := t.(type) { + case nil: + b.AppendNull() + + case string: + f, err := strconv.ParseFloat(v, 8*8) + if err != nil { + return &json.UnmarshalTypeError{ + Value: v, + Type: reflect.TypeOf(float64(0)), + Offset: dec.InputOffset(), + } + } + b.Append(float64(f)) + case float64: + b.Append(float64(v)) + case json.Number: + f, err := strconv.ParseFloat(v.String(), 8*8) + if err != nil { + return &json.UnmarshalTypeError{ + Value: v.String(), + Type: reflect.TypeOf(float64(0)), + Offset: dec.InputOffset(), + } + } + b.Append(float64(f)) + + default: + return &json.UnmarshalTypeError{ + Value: fmt.Sprint(t), + Type: reflect.TypeOf(float64(0)), + Offset: dec.InputOffset(), + } + } + + return nil +} + +func (b *Float64Builder) Unmarshal(dec *json.Decoder) error { + for dec.More() { + if err := b.UnmarshalOne(dec); err != nil { + return err + } + } + return nil +} + +func (b *Float64Builder) UnmarshalJSON(data []byte) error { + dec := json.NewDecoder(bytes.NewReader(data)) + t, err := dec.Token() + if err != nil { + return err + } + + if delim, ok := t.(json.Delim); !ok || delim != '[' { + return fmt.Errorf("binary builder must unpack from json array, found %s", delim) + } + + return b.Unmarshal(dec) +} + +type Int32Builder struct { + builder + + data *memory.Buffer + rawData []int32 +} + +func NewInt32Builder(mem memory.Allocator) *Int32Builder { + return &Int32Builder{builder: builder{refCount: 1, mem: mem}} +} + +func (b *Int32Builder) Type() arrow.DataType { return arrow.PrimitiveTypes.Int32 } + +// Release decreases the reference count by 1. +// When the reference count goes to zero, the memory is freed. +func (b *Int32Builder) Release() { + debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases") + + if atomic.AddInt64(&b.refCount, -1) == 0 { + if b.nullBitmap != nil { + b.nullBitmap.Release() + b.nullBitmap = nil + } + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + } +} + +func (b *Int32Builder) Append(v int32) { + b.Reserve(1) + b.UnsafeAppend(v) +} + +func (b *Int32Builder) AppendNull() { + b.Reserve(1) + b.UnsafeAppendBoolToBitmap(false) +} + +func (b *Int32Builder) AppendNulls(n int) { + for i := 0; i < n; i++ { + b.AppendNull() + } +} + +func (b *Int32Builder) AppendEmptyValue() { + b.Append(0) +} + +func (b *Int32Builder) AppendEmptyValues(n int) { + for i := 0; i < n; i++ { + b.AppendEmptyValue() + } +} + +func (b *Int32Builder) UnsafeAppend(v int32) { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + b.rawData[b.length] = v + b.length++ +} + +func (b *Int32Builder) UnsafeAppendBoolToBitmap(isValid bool) { + if isValid { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + } else { + b.nulls++ + } + b.length++ +} + +// AppendValues will append the values in the v slice. The valid slice determines which values +// in v are valid (not null). The valid slice must either be empty or be equal in length to v. If empty, +// all values in v are appended and considered valid. +func (b *Int32Builder) AppendValues(v []int32, valid []bool) { + if len(v) != len(valid) && len(valid) != 0 { + panic("len(v) != len(valid) && len(valid) != 0") + } + + if len(v) == 0 { + return + } + + b.Reserve(len(v)) + arrow.Int32Traits.Copy(b.rawData[b.length:], v) + b.builder.unsafeAppendBoolsToBitmap(valid, len(v)) +} + +func (b *Int32Builder) init(capacity int) { + b.builder.init(capacity) + + b.data = memory.NewResizableBuffer(b.mem) + bytesN := arrow.Int32Traits.BytesRequired(capacity) + b.data.Resize(bytesN) + b.rawData = arrow.Int32Traits.CastFromBytes(b.data.Bytes()) +} + +// Reserve ensures there is enough space for appending n elements +// by checking the capacity and calling Resize if necessary. +func (b *Int32Builder) Reserve(n int) { + b.builder.reserve(n, b.Resize) +} + +// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(), +// additional memory will be allocated. If n is smaller, the allocated memory may reduced. +func (b *Int32Builder) Resize(n int) { + nBuilder := n + if n < minBuilderCapacity { + n = minBuilderCapacity + } + + if b.capacity == 0 { + b.init(n) + } else { + b.builder.resize(nBuilder, b.init) + b.data.Resize(arrow.Int32Traits.BytesRequired(n)) + b.rawData = arrow.Int32Traits.CastFromBytes(b.data.Bytes()) + } +} + +func (b *Int32Builder) Value(i int) int32 { + return b.rawData[i] +} + +// NewArray creates a Int32 array from the memory buffers used by the builder and resets the Int32Builder +// so it can be used to build a new array. +func (b *Int32Builder) NewArray() arrow.Array { + return b.NewInt32Array() +} + +// NewInt32Array creates a Int32 array from the memory buffers used by the builder and resets the Int32Builder +// so it can be used to build a new array. +func (b *Int32Builder) NewInt32Array() (a *Int32) { + data := b.newData() + a = NewInt32Data(data) + data.Release() + return +} + +func (b *Int32Builder) newData() (data *Data) { + bytesRequired := arrow.Int32Traits.BytesRequired(b.length) + if bytesRequired > 0 && bytesRequired < b.data.Len() { + // trim buffers + b.data.Resize(bytesRequired) + } + data = NewData(arrow.PrimitiveTypes.Int32, b.length, []*memory.Buffer{b.nullBitmap, b.data}, nil, b.nulls, 0) + b.reset() + + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + + return +} + +func (b *Int32Builder) AppendValueFromString(s string) error { + if s == NullValueStr { + b.AppendNull() + return nil + } + v, err := strconv.ParseInt(s, 10, 4*8) + if err != nil { + b.AppendNull() + return err + } + b.Append(int32(v)) + return nil +} + +func (b *Int32Builder) UnmarshalOne(dec *json.Decoder) error { + t, err := dec.Token() + if err != nil { + return err + } + + switch v := t.(type) { + case nil: + b.AppendNull() + + case string: + f, err := strconv.ParseInt(v, 10, 4*8) + if err != nil { + return &json.UnmarshalTypeError{ + Value: v, + Type: reflect.TypeOf(int32(0)), + Offset: dec.InputOffset(), + } + } + b.Append(int32(f)) + case float64: + b.Append(int32(v)) + case json.Number: + f, err := strconv.ParseInt(v.String(), 10, 4*8) + if err != nil { + return &json.UnmarshalTypeError{ + Value: v.String(), + Type: reflect.TypeOf(int32(0)), + Offset: dec.InputOffset(), + } + } + b.Append(int32(f)) + + default: + return &json.UnmarshalTypeError{ + Value: fmt.Sprint(t), + Type: reflect.TypeOf(int32(0)), + Offset: dec.InputOffset(), + } + } + + return nil +} + +func (b *Int32Builder) Unmarshal(dec *json.Decoder) error { + for dec.More() { + if err := b.UnmarshalOne(dec); err != nil { + return err + } + } + return nil +} + +func (b *Int32Builder) UnmarshalJSON(data []byte) error { + dec := json.NewDecoder(bytes.NewReader(data)) + t, err := dec.Token() + if err != nil { + return err + } + + if delim, ok := t.(json.Delim); !ok || delim != '[' { + return fmt.Errorf("binary builder must unpack from json array, found %s", delim) + } + + return b.Unmarshal(dec) +} + +type Uint32Builder struct { + builder + + data *memory.Buffer + rawData []uint32 +} + +func NewUint32Builder(mem memory.Allocator) *Uint32Builder { + return &Uint32Builder{builder: builder{refCount: 1, mem: mem}} +} + +func (b *Uint32Builder) Type() arrow.DataType { return arrow.PrimitiveTypes.Uint32 } + +// Release decreases the reference count by 1. +// When the reference count goes to zero, the memory is freed. +func (b *Uint32Builder) Release() { + debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases") + + if atomic.AddInt64(&b.refCount, -1) == 0 { + if b.nullBitmap != nil { + b.nullBitmap.Release() + b.nullBitmap = nil + } + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + } +} + +func (b *Uint32Builder) Append(v uint32) { + b.Reserve(1) + b.UnsafeAppend(v) +} + +func (b *Uint32Builder) AppendNull() { + b.Reserve(1) + b.UnsafeAppendBoolToBitmap(false) +} + +func (b *Uint32Builder) AppendNulls(n int) { + for i := 0; i < n; i++ { + b.AppendNull() + } +} + +func (b *Uint32Builder) AppendEmptyValue() { + b.Append(0) +} + +func (b *Uint32Builder) AppendEmptyValues(n int) { + for i := 0; i < n; i++ { + b.AppendEmptyValue() + } +} + +func (b *Uint32Builder) UnsafeAppend(v uint32) { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + b.rawData[b.length] = v + b.length++ +} + +func (b *Uint32Builder) UnsafeAppendBoolToBitmap(isValid bool) { + if isValid { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + } else { + b.nulls++ + } + b.length++ +} + +// AppendValues will append the values in the v slice. The valid slice determines which values +// in v are valid (not null). The valid slice must either be empty or be equal in length to v. If empty, +// all values in v are appended and considered valid. +func (b *Uint32Builder) AppendValues(v []uint32, valid []bool) { + if len(v) != len(valid) && len(valid) != 0 { + panic("len(v) != len(valid) && len(valid) != 0") + } + + if len(v) == 0 { + return + } + + b.Reserve(len(v)) + arrow.Uint32Traits.Copy(b.rawData[b.length:], v) + b.builder.unsafeAppendBoolsToBitmap(valid, len(v)) +} + +func (b *Uint32Builder) init(capacity int) { + b.builder.init(capacity) + + b.data = memory.NewResizableBuffer(b.mem) + bytesN := arrow.Uint32Traits.BytesRequired(capacity) + b.data.Resize(bytesN) + b.rawData = arrow.Uint32Traits.CastFromBytes(b.data.Bytes()) +} + +// Reserve ensures there is enough space for appending n elements +// by checking the capacity and calling Resize if necessary. +func (b *Uint32Builder) Reserve(n int) { + b.builder.reserve(n, b.Resize) +} + +// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(), +// additional memory will be allocated. If n is smaller, the allocated memory may reduced. +func (b *Uint32Builder) Resize(n int) { + nBuilder := n + if n < minBuilderCapacity { + n = minBuilderCapacity + } + + if b.capacity == 0 { + b.init(n) + } else { + b.builder.resize(nBuilder, b.init) + b.data.Resize(arrow.Uint32Traits.BytesRequired(n)) + b.rawData = arrow.Uint32Traits.CastFromBytes(b.data.Bytes()) + } +} + +func (b *Uint32Builder) Value(i int) uint32 { + return b.rawData[i] +} + +// NewArray creates a Uint32 array from the memory buffers used by the builder and resets the Uint32Builder +// so it can be used to build a new array. +func (b *Uint32Builder) NewArray() arrow.Array { + return b.NewUint32Array() +} + +// NewUint32Array creates a Uint32 array from the memory buffers used by the builder and resets the Uint32Builder +// so it can be used to build a new array. +func (b *Uint32Builder) NewUint32Array() (a *Uint32) { + data := b.newData() + a = NewUint32Data(data) + data.Release() + return +} + +func (b *Uint32Builder) newData() (data *Data) { + bytesRequired := arrow.Uint32Traits.BytesRequired(b.length) + if bytesRequired > 0 && bytesRequired < b.data.Len() { + // trim buffers + b.data.Resize(bytesRequired) + } + data = NewData(arrow.PrimitiveTypes.Uint32, b.length, []*memory.Buffer{b.nullBitmap, b.data}, nil, b.nulls, 0) + b.reset() + + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + + return +} + +func (b *Uint32Builder) AppendValueFromString(s string) error { + if s == NullValueStr { + b.AppendNull() + return nil + } + v, err := strconv.ParseUint(s, 10, 4*8) + if err != nil { + b.AppendNull() + return err + } + b.Append(uint32(v)) + return nil +} + +func (b *Uint32Builder) UnmarshalOne(dec *json.Decoder) error { + t, err := dec.Token() + if err != nil { + return err + } + + switch v := t.(type) { + case nil: + b.AppendNull() + + case string: + f, err := strconv.ParseUint(v, 10, 4*8) + if err != nil { + return &json.UnmarshalTypeError{ + Value: v, + Type: reflect.TypeOf(uint32(0)), + Offset: dec.InputOffset(), + } + } + b.Append(uint32(f)) + case float64: + b.Append(uint32(v)) + case json.Number: + f, err := strconv.ParseUint(v.String(), 10, 4*8) + if err != nil { + return &json.UnmarshalTypeError{ + Value: v.String(), + Type: reflect.TypeOf(uint32(0)), + Offset: dec.InputOffset(), + } + } + b.Append(uint32(f)) + + default: + return &json.UnmarshalTypeError{ + Value: fmt.Sprint(t), + Type: reflect.TypeOf(uint32(0)), + Offset: dec.InputOffset(), + } + } + + return nil +} + +func (b *Uint32Builder) Unmarshal(dec *json.Decoder) error { + for dec.More() { + if err := b.UnmarshalOne(dec); err != nil { + return err + } + } + return nil +} + +func (b *Uint32Builder) UnmarshalJSON(data []byte) error { + dec := json.NewDecoder(bytes.NewReader(data)) + t, err := dec.Token() + if err != nil { + return err + } + + if delim, ok := t.(json.Delim); !ok || delim != '[' { + return fmt.Errorf("binary builder must unpack from json array, found %s", delim) + } + + return b.Unmarshal(dec) +} + +type Float32Builder struct { + builder + + data *memory.Buffer + rawData []float32 +} + +func NewFloat32Builder(mem memory.Allocator) *Float32Builder { + return &Float32Builder{builder: builder{refCount: 1, mem: mem}} +} + +func (b *Float32Builder) Type() arrow.DataType { return arrow.PrimitiveTypes.Float32 } + +// Release decreases the reference count by 1. +// When the reference count goes to zero, the memory is freed. +func (b *Float32Builder) Release() { + debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases") + + if atomic.AddInt64(&b.refCount, -1) == 0 { + if b.nullBitmap != nil { + b.nullBitmap.Release() + b.nullBitmap = nil + } + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + } +} + +func (b *Float32Builder) Append(v float32) { + b.Reserve(1) + b.UnsafeAppend(v) +} + +func (b *Float32Builder) AppendNull() { + b.Reserve(1) + b.UnsafeAppendBoolToBitmap(false) +} + +func (b *Float32Builder) AppendNulls(n int) { + for i := 0; i < n; i++ { + b.AppendNull() + } +} + +func (b *Float32Builder) AppendEmptyValue() { + b.Append(0) +} + +func (b *Float32Builder) AppendEmptyValues(n int) { + for i := 0; i < n; i++ { + b.AppendEmptyValue() + } +} + +func (b *Float32Builder) UnsafeAppend(v float32) { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + b.rawData[b.length] = v + b.length++ +} + +func (b *Float32Builder) UnsafeAppendBoolToBitmap(isValid bool) { + if isValid { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + } else { + b.nulls++ + } + b.length++ +} + +// AppendValues will append the values in the v slice. The valid slice determines which values +// in v are valid (not null). The valid slice must either be empty or be equal in length to v. If empty, +// all values in v are appended and considered valid. +func (b *Float32Builder) AppendValues(v []float32, valid []bool) { + if len(v) != len(valid) && len(valid) != 0 { + panic("len(v) != len(valid) && len(valid) != 0") + } + + if len(v) == 0 { + return + } + + b.Reserve(len(v)) + arrow.Float32Traits.Copy(b.rawData[b.length:], v) + b.builder.unsafeAppendBoolsToBitmap(valid, len(v)) +} + +func (b *Float32Builder) init(capacity int) { + b.builder.init(capacity) + + b.data = memory.NewResizableBuffer(b.mem) + bytesN := arrow.Float32Traits.BytesRequired(capacity) + b.data.Resize(bytesN) + b.rawData = arrow.Float32Traits.CastFromBytes(b.data.Bytes()) +} + +// Reserve ensures there is enough space for appending n elements +// by checking the capacity and calling Resize if necessary. +func (b *Float32Builder) Reserve(n int) { + b.builder.reserve(n, b.Resize) +} + +// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(), +// additional memory will be allocated. If n is smaller, the allocated memory may reduced. +func (b *Float32Builder) Resize(n int) { + nBuilder := n + if n < minBuilderCapacity { + n = minBuilderCapacity + } + + if b.capacity == 0 { + b.init(n) + } else { + b.builder.resize(nBuilder, b.init) + b.data.Resize(arrow.Float32Traits.BytesRequired(n)) + b.rawData = arrow.Float32Traits.CastFromBytes(b.data.Bytes()) + } +} + +func (b *Float32Builder) Value(i int) float32 { + return b.rawData[i] +} + +// NewArray creates a Float32 array from the memory buffers used by the builder and resets the Float32Builder +// so it can be used to build a new array. +func (b *Float32Builder) NewArray() arrow.Array { + return b.NewFloat32Array() +} + +// NewFloat32Array creates a Float32 array from the memory buffers used by the builder and resets the Float32Builder +// so it can be used to build a new array. +func (b *Float32Builder) NewFloat32Array() (a *Float32) { + data := b.newData() + a = NewFloat32Data(data) + data.Release() + return +} + +func (b *Float32Builder) newData() (data *Data) { + bytesRequired := arrow.Float32Traits.BytesRequired(b.length) + if bytesRequired > 0 && bytesRequired < b.data.Len() { + // trim buffers + b.data.Resize(bytesRequired) + } + data = NewData(arrow.PrimitiveTypes.Float32, b.length, []*memory.Buffer{b.nullBitmap, b.data}, nil, b.nulls, 0) + b.reset() + + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + + return +} + +func (b *Float32Builder) AppendValueFromString(s string) error { + if s == NullValueStr { + b.AppendNull() + return nil + } + v, err := strconv.ParseFloat(s, 4*8) + if err != nil { + b.AppendNull() + return err + } + b.Append(float32(v)) + return nil +} + +func (b *Float32Builder) UnmarshalOne(dec *json.Decoder) error { + t, err := dec.Token() + if err != nil { + return err + } + + switch v := t.(type) { + case nil: + b.AppendNull() + + case string: + f, err := strconv.ParseFloat(v, 4*8) + if err != nil { + return &json.UnmarshalTypeError{ + Value: v, + Type: reflect.TypeOf(float32(0)), + Offset: dec.InputOffset(), + } + } + b.Append(float32(f)) + case float64: + b.Append(float32(v)) + case json.Number: + f, err := strconv.ParseFloat(v.String(), 4*8) + if err != nil { + return &json.UnmarshalTypeError{ + Value: v.String(), + Type: reflect.TypeOf(float32(0)), + Offset: dec.InputOffset(), + } + } + b.Append(float32(f)) + + default: + return &json.UnmarshalTypeError{ + Value: fmt.Sprint(t), + Type: reflect.TypeOf(float32(0)), + Offset: dec.InputOffset(), + } + } + + return nil +} + +func (b *Float32Builder) Unmarshal(dec *json.Decoder) error { + for dec.More() { + if err := b.UnmarshalOne(dec); err != nil { + return err + } + } + return nil +} + +func (b *Float32Builder) UnmarshalJSON(data []byte) error { + dec := json.NewDecoder(bytes.NewReader(data)) + t, err := dec.Token() + if err != nil { + return err + } + + if delim, ok := t.(json.Delim); !ok || delim != '[' { + return fmt.Errorf("binary builder must unpack from json array, found %s", delim) + } + + return b.Unmarshal(dec) +} + +type Int16Builder struct { + builder + + data *memory.Buffer + rawData []int16 +} + +func NewInt16Builder(mem memory.Allocator) *Int16Builder { + return &Int16Builder{builder: builder{refCount: 1, mem: mem}} +} + +func (b *Int16Builder) Type() arrow.DataType { return arrow.PrimitiveTypes.Int16 } + +// Release decreases the reference count by 1. +// When the reference count goes to zero, the memory is freed. +func (b *Int16Builder) Release() { + debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases") + + if atomic.AddInt64(&b.refCount, -1) == 0 { + if b.nullBitmap != nil { + b.nullBitmap.Release() + b.nullBitmap = nil + } + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + } +} + +func (b *Int16Builder) Append(v int16) { + b.Reserve(1) + b.UnsafeAppend(v) +} + +func (b *Int16Builder) AppendNull() { + b.Reserve(1) + b.UnsafeAppendBoolToBitmap(false) +} + +func (b *Int16Builder) AppendNulls(n int) { + for i := 0; i < n; i++ { + b.AppendNull() + } +} + +func (b *Int16Builder) AppendEmptyValue() { + b.Append(0) +} + +func (b *Int16Builder) AppendEmptyValues(n int) { + for i := 0; i < n; i++ { + b.AppendEmptyValue() + } +} + +func (b *Int16Builder) UnsafeAppend(v int16) { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + b.rawData[b.length] = v + b.length++ +} + +func (b *Int16Builder) UnsafeAppendBoolToBitmap(isValid bool) { + if isValid { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + } else { + b.nulls++ + } + b.length++ +} + +// AppendValues will append the values in the v slice. The valid slice determines which values +// in v are valid (not null). The valid slice must either be empty or be equal in length to v. If empty, +// all values in v are appended and considered valid. +func (b *Int16Builder) AppendValues(v []int16, valid []bool) { + if len(v) != len(valid) && len(valid) != 0 { + panic("len(v) != len(valid) && len(valid) != 0") + } + + if len(v) == 0 { + return + } + + b.Reserve(len(v)) + arrow.Int16Traits.Copy(b.rawData[b.length:], v) + b.builder.unsafeAppendBoolsToBitmap(valid, len(v)) +} + +func (b *Int16Builder) init(capacity int) { + b.builder.init(capacity) + + b.data = memory.NewResizableBuffer(b.mem) + bytesN := arrow.Int16Traits.BytesRequired(capacity) + b.data.Resize(bytesN) + b.rawData = arrow.Int16Traits.CastFromBytes(b.data.Bytes()) +} + +// Reserve ensures there is enough space for appending n elements +// by checking the capacity and calling Resize if necessary. +func (b *Int16Builder) Reserve(n int) { + b.builder.reserve(n, b.Resize) +} + +// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(), +// additional memory will be allocated. If n is smaller, the allocated memory may reduced. +func (b *Int16Builder) Resize(n int) { + nBuilder := n + if n < minBuilderCapacity { + n = minBuilderCapacity + } + + if b.capacity == 0 { + b.init(n) + } else { + b.builder.resize(nBuilder, b.init) + b.data.Resize(arrow.Int16Traits.BytesRequired(n)) + b.rawData = arrow.Int16Traits.CastFromBytes(b.data.Bytes()) + } +} + +func (b *Int16Builder) Value(i int) int16 { + return b.rawData[i] +} + +// NewArray creates a Int16 array from the memory buffers used by the builder and resets the Int16Builder +// so it can be used to build a new array. +func (b *Int16Builder) NewArray() arrow.Array { + return b.NewInt16Array() +} + +// NewInt16Array creates a Int16 array from the memory buffers used by the builder and resets the Int16Builder +// so it can be used to build a new array. +func (b *Int16Builder) NewInt16Array() (a *Int16) { + data := b.newData() + a = NewInt16Data(data) + data.Release() + return +} + +func (b *Int16Builder) newData() (data *Data) { + bytesRequired := arrow.Int16Traits.BytesRequired(b.length) + if bytesRequired > 0 && bytesRequired < b.data.Len() { + // trim buffers + b.data.Resize(bytesRequired) + } + data = NewData(arrow.PrimitiveTypes.Int16, b.length, []*memory.Buffer{b.nullBitmap, b.data}, nil, b.nulls, 0) + b.reset() + + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + + return +} + +func (b *Int16Builder) AppendValueFromString(s string) error { + if s == NullValueStr { + b.AppendNull() + return nil + } + v, err := strconv.ParseInt(s, 10, 2*8) + if err != nil { + b.AppendNull() + return err + } + b.Append(int16(v)) + return nil +} + +func (b *Int16Builder) UnmarshalOne(dec *json.Decoder) error { + t, err := dec.Token() + if err != nil { + return err + } + + switch v := t.(type) { + case nil: + b.AppendNull() + + case string: + f, err := strconv.ParseInt(v, 10, 2*8) + if err != nil { + return &json.UnmarshalTypeError{ + Value: v, + Type: reflect.TypeOf(int16(0)), + Offset: dec.InputOffset(), + } + } + b.Append(int16(f)) + case float64: + b.Append(int16(v)) + case json.Number: + f, err := strconv.ParseInt(v.String(), 10, 2*8) + if err != nil { + return &json.UnmarshalTypeError{ + Value: v.String(), + Type: reflect.TypeOf(int16(0)), + Offset: dec.InputOffset(), + } + } + b.Append(int16(f)) + + default: + return &json.UnmarshalTypeError{ + Value: fmt.Sprint(t), + Type: reflect.TypeOf(int16(0)), + Offset: dec.InputOffset(), + } + } + + return nil +} + +func (b *Int16Builder) Unmarshal(dec *json.Decoder) error { + for dec.More() { + if err := b.UnmarshalOne(dec); err != nil { + return err + } + } + return nil +} + +func (b *Int16Builder) UnmarshalJSON(data []byte) error { + dec := json.NewDecoder(bytes.NewReader(data)) + t, err := dec.Token() + if err != nil { + return err + } + + if delim, ok := t.(json.Delim); !ok || delim != '[' { + return fmt.Errorf("binary builder must unpack from json array, found %s", delim) + } + + return b.Unmarshal(dec) +} + +type Uint16Builder struct { + builder + + data *memory.Buffer + rawData []uint16 +} + +func NewUint16Builder(mem memory.Allocator) *Uint16Builder { + return &Uint16Builder{builder: builder{refCount: 1, mem: mem}} +} + +func (b *Uint16Builder) Type() arrow.DataType { return arrow.PrimitiveTypes.Uint16 } + +// Release decreases the reference count by 1. +// When the reference count goes to zero, the memory is freed. +func (b *Uint16Builder) Release() { + debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases") + + if atomic.AddInt64(&b.refCount, -1) == 0 { + if b.nullBitmap != nil { + b.nullBitmap.Release() + b.nullBitmap = nil + } + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + } +} + +func (b *Uint16Builder) Append(v uint16) { + b.Reserve(1) + b.UnsafeAppend(v) +} + +func (b *Uint16Builder) AppendNull() { + b.Reserve(1) + b.UnsafeAppendBoolToBitmap(false) +} + +func (b *Uint16Builder) AppendNulls(n int) { + for i := 0; i < n; i++ { + b.AppendNull() + } +} + +func (b *Uint16Builder) AppendEmptyValue() { + b.Append(0) +} + +func (b *Uint16Builder) AppendEmptyValues(n int) { + for i := 0; i < n; i++ { + b.AppendEmptyValue() + } +} + +func (b *Uint16Builder) UnsafeAppend(v uint16) { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + b.rawData[b.length] = v + b.length++ +} + +func (b *Uint16Builder) UnsafeAppendBoolToBitmap(isValid bool) { + if isValid { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + } else { + b.nulls++ + } + b.length++ +} + +// AppendValues will append the values in the v slice. The valid slice determines which values +// in v are valid (not null). The valid slice must either be empty or be equal in length to v. If empty, +// all values in v are appended and considered valid. +func (b *Uint16Builder) AppendValues(v []uint16, valid []bool) { + if len(v) != len(valid) && len(valid) != 0 { + panic("len(v) != len(valid) && len(valid) != 0") + } + + if len(v) == 0 { + return + } + + b.Reserve(len(v)) + arrow.Uint16Traits.Copy(b.rawData[b.length:], v) + b.builder.unsafeAppendBoolsToBitmap(valid, len(v)) +} + +func (b *Uint16Builder) init(capacity int) { + b.builder.init(capacity) + + b.data = memory.NewResizableBuffer(b.mem) + bytesN := arrow.Uint16Traits.BytesRequired(capacity) + b.data.Resize(bytesN) + b.rawData = arrow.Uint16Traits.CastFromBytes(b.data.Bytes()) +} + +// Reserve ensures there is enough space for appending n elements +// by checking the capacity and calling Resize if necessary. +func (b *Uint16Builder) Reserve(n int) { + b.builder.reserve(n, b.Resize) +} + +// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(), +// additional memory will be allocated. If n is smaller, the allocated memory may reduced. +func (b *Uint16Builder) Resize(n int) { + nBuilder := n + if n < minBuilderCapacity { + n = minBuilderCapacity + } + + if b.capacity == 0 { + b.init(n) + } else { + b.builder.resize(nBuilder, b.init) + b.data.Resize(arrow.Uint16Traits.BytesRequired(n)) + b.rawData = arrow.Uint16Traits.CastFromBytes(b.data.Bytes()) + } +} + +func (b *Uint16Builder) Value(i int) uint16 { + return b.rawData[i] +} + +// NewArray creates a Uint16 array from the memory buffers used by the builder and resets the Uint16Builder +// so it can be used to build a new array. +func (b *Uint16Builder) NewArray() arrow.Array { + return b.NewUint16Array() +} + +// NewUint16Array creates a Uint16 array from the memory buffers used by the builder and resets the Uint16Builder +// so it can be used to build a new array. +func (b *Uint16Builder) NewUint16Array() (a *Uint16) { + data := b.newData() + a = NewUint16Data(data) + data.Release() + return +} + +func (b *Uint16Builder) newData() (data *Data) { + bytesRequired := arrow.Uint16Traits.BytesRequired(b.length) + if bytesRequired > 0 && bytesRequired < b.data.Len() { + // trim buffers + b.data.Resize(bytesRequired) + } + data = NewData(arrow.PrimitiveTypes.Uint16, b.length, []*memory.Buffer{b.nullBitmap, b.data}, nil, b.nulls, 0) + b.reset() + + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + + return +} + +func (b *Uint16Builder) AppendValueFromString(s string) error { + if s == NullValueStr { + b.AppendNull() + return nil + } + v, err := strconv.ParseUint(s, 10, 2*8) + if err != nil { + b.AppendNull() + return err + } + b.Append(uint16(v)) + return nil +} + +func (b *Uint16Builder) UnmarshalOne(dec *json.Decoder) error { + t, err := dec.Token() + if err != nil { + return err + } + + switch v := t.(type) { + case nil: + b.AppendNull() + + case string: + f, err := strconv.ParseUint(v, 10, 2*8) + if err != nil { + return &json.UnmarshalTypeError{ + Value: v, + Type: reflect.TypeOf(uint16(0)), + Offset: dec.InputOffset(), + } + } + b.Append(uint16(f)) + case float64: + b.Append(uint16(v)) + case json.Number: + f, err := strconv.ParseUint(v.String(), 10, 2*8) + if err != nil { + return &json.UnmarshalTypeError{ + Value: v.String(), + Type: reflect.TypeOf(uint16(0)), + Offset: dec.InputOffset(), + } + } + b.Append(uint16(f)) + + default: + return &json.UnmarshalTypeError{ + Value: fmt.Sprint(t), + Type: reflect.TypeOf(uint16(0)), + Offset: dec.InputOffset(), + } + } + + return nil +} + +func (b *Uint16Builder) Unmarshal(dec *json.Decoder) error { + for dec.More() { + if err := b.UnmarshalOne(dec); err != nil { + return err + } + } + return nil +} + +func (b *Uint16Builder) UnmarshalJSON(data []byte) error { + dec := json.NewDecoder(bytes.NewReader(data)) + t, err := dec.Token() + if err != nil { + return err + } + + if delim, ok := t.(json.Delim); !ok || delim != '[' { + return fmt.Errorf("binary builder must unpack from json array, found %s", delim) + } + + return b.Unmarshal(dec) +} + +type Int8Builder struct { + builder + + data *memory.Buffer + rawData []int8 +} + +func NewInt8Builder(mem memory.Allocator) *Int8Builder { + return &Int8Builder{builder: builder{refCount: 1, mem: mem}} +} + +func (b *Int8Builder) Type() arrow.DataType { return arrow.PrimitiveTypes.Int8 } + +// Release decreases the reference count by 1. +// When the reference count goes to zero, the memory is freed. +func (b *Int8Builder) Release() { + debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases") + + if atomic.AddInt64(&b.refCount, -1) == 0 { + if b.nullBitmap != nil { + b.nullBitmap.Release() + b.nullBitmap = nil + } + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + } +} + +func (b *Int8Builder) Append(v int8) { + b.Reserve(1) + b.UnsafeAppend(v) +} + +func (b *Int8Builder) AppendNull() { + b.Reserve(1) + b.UnsafeAppendBoolToBitmap(false) +} + +func (b *Int8Builder) AppendNulls(n int) { + for i := 0; i < n; i++ { + b.AppendNull() + } +} + +func (b *Int8Builder) AppendEmptyValue() { + b.Append(0) +} + +func (b *Int8Builder) AppendEmptyValues(n int) { + for i := 0; i < n; i++ { + b.AppendEmptyValue() + } +} + +func (b *Int8Builder) UnsafeAppend(v int8) { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + b.rawData[b.length] = v + b.length++ +} + +func (b *Int8Builder) UnsafeAppendBoolToBitmap(isValid bool) { + if isValid { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + } else { + b.nulls++ + } + b.length++ +} + +// AppendValues will append the values in the v slice. The valid slice determines which values +// in v are valid (not null). The valid slice must either be empty or be equal in length to v. If empty, +// all values in v are appended and considered valid. +func (b *Int8Builder) AppendValues(v []int8, valid []bool) { + if len(v) != len(valid) && len(valid) != 0 { + panic("len(v) != len(valid) && len(valid) != 0") + } + + if len(v) == 0 { + return + } + + b.Reserve(len(v)) + arrow.Int8Traits.Copy(b.rawData[b.length:], v) + b.builder.unsafeAppendBoolsToBitmap(valid, len(v)) +} + +func (b *Int8Builder) init(capacity int) { + b.builder.init(capacity) + + b.data = memory.NewResizableBuffer(b.mem) + bytesN := arrow.Int8Traits.BytesRequired(capacity) + b.data.Resize(bytesN) + b.rawData = arrow.Int8Traits.CastFromBytes(b.data.Bytes()) +} + +// Reserve ensures there is enough space for appending n elements +// by checking the capacity and calling Resize if necessary. +func (b *Int8Builder) Reserve(n int) { + b.builder.reserve(n, b.Resize) +} + +// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(), +// additional memory will be allocated. If n is smaller, the allocated memory may reduced. +func (b *Int8Builder) Resize(n int) { + nBuilder := n + if n < minBuilderCapacity { + n = minBuilderCapacity + } + + if b.capacity == 0 { + b.init(n) + } else { + b.builder.resize(nBuilder, b.init) + b.data.Resize(arrow.Int8Traits.BytesRequired(n)) + b.rawData = arrow.Int8Traits.CastFromBytes(b.data.Bytes()) + } +} + +func (b *Int8Builder) Value(i int) int8 { + return b.rawData[i] +} + +// NewArray creates a Int8 array from the memory buffers used by the builder and resets the Int8Builder +// so it can be used to build a new array. +func (b *Int8Builder) NewArray() arrow.Array { + return b.NewInt8Array() +} + +// NewInt8Array creates a Int8 array from the memory buffers used by the builder and resets the Int8Builder +// so it can be used to build a new array. +func (b *Int8Builder) NewInt8Array() (a *Int8) { + data := b.newData() + a = NewInt8Data(data) + data.Release() + return +} + +func (b *Int8Builder) newData() (data *Data) { + bytesRequired := arrow.Int8Traits.BytesRequired(b.length) + if bytesRequired > 0 && bytesRequired < b.data.Len() { + // trim buffers + b.data.Resize(bytesRequired) + } + data = NewData(arrow.PrimitiveTypes.Int8, b.length, []*memory.Buffer{b.nullBitmap, b.data}, nil, b.nulls, 0) + b.reset() + + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + + return +} + +func (b *Int8Builder) AppendValueFromString(s string) error { + if s == NullValueStr { + b.AppendNull() + return nil + } + v, err := strconv.ParseInt(s, 10, 1*8) + if err != nil { + b.AppendNull() + return err + } + b.Append(int8(v)) + return nil +} + +func (b *Int8Builder) UnmarshalOne(dec *json.Decoder) error { + t, err := dec.Token() + if err != nil { + return err + } + + switch v := t.(type) { + case nil: + b.AppendNull() + + case string: + f, err := strconv.ParseInt(v, 10, 1*8) + if err != nil { + return &json.UnmarshalTypeError{ + Value: v, + Type: reflect.TypeOf(int8(0)), + Offset: dec.InputOffset(), + } + } + b.Append(int8(f)) + case float64: + b.Append(int8(v)) + case json.Number: + f, err := strconv.ParseInt(v.String(), 10, 1*8) + if err != nil { + return &json.UnmarshalTypeError{ + Value: v.String(), + Type: reflect.TypeOf(int8(0)), + Offset: dec.InputOffset(), + } + } + b.Append(int8(f)) + + default: + return &json.UnmarshalTypeError{ + Value: fmt.Sprint(t), + Type: reflect.TypeOf(int8(0)), + Offset: dec.InputOffset(), + } + } + + return nil +} + +func (b *Int8Builder) Unmarshal(dec *json.Decoder) error { + for dec.More() { + if err := b.UnmarshalOne(dec); err != nil { + return err + } + } + return nil +} + +func (b *Int8Builder) UnmarshalJSON(data []byte) error { + dec := json.NewDecoder(bytes.NewReader(data)) + t, err := dec.Token() + if err != nil { + return err + } + + if delim, ok := t.(json.Delim); !ok || delim != '[' { + return fmt.Errorf("binary builder must unpack from json array, found %s", delim) + } + + return b.Unmarshal(dec) +} + +type Uint8Builder struct { + builder + + data *memory.Buffer + rawData []uint8 +} + +func NewUint8Builder(mem memory.Allocator) *Uint8Builder { + return &Uint8Builder{builder: builder{refCount: 1, mem: mem}} +} + +func (b *Uint8Builder) Type() arrow.DataType { return arrow.PrimitiveTypes.Uint8 } + +// Release decreases the reference count by 1. +// When the reference count goes to zero, the memory is freed. +func (b *Uint8Builder) Release() { + debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases") + + if atomic.AddInt64(&b.refCount, -1) == 0 { + if b.nullBitmap != nil { + b.nullBitmap.Release() + b.nullBitmap = nil + } + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + } +} + +func (b *Uint8Builder) Append(v uint8) { + b.Reserve(1) + b.UnsafeAppend(v) +} + +func (b *Uint8Builder) AppendNull() { + b.Reserve(1) + b.UnsafeAppendBoolToBitmap(false) +} + +func (b *Uint8Builder) AppendNulls(n int) { + for i := 0; i < n; i++ { + b.AppendNull() + } +} + +func (b *Uint8Builder) AppendEmptyValue() { + b.Append(0) +} + +func (b *Uint8Builder) AppendEmptyValues(n int) { + for i := 0; i < n; i++ { + b.AppendEmptyValue() + } +} + +func (b *Uint8Builder) UnsafeAppend(v uint8) { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + b.rawData[b.length] = v + b.length++ +} + +func (b *Uint8Builder) UnsafeAppendBoolToBitmap(isValid bool) { + if isValid { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + } else { + b.nulls++ + } + b.length++ +} + +// AppendValues will append the values in the v slice. The valid slice determines which values +// in v are valid (not null). The valid slice must either be empty or be equal in length to v. If empty, +// all values in v are appended and considered valid. +func (b *Uint8Builder) AppendValues(v []uint8, valid []bool) { + if len(v) != len(valid) && len(valid) != 0 { + panic("len(v) != len(valid) && len(valid) != 0") + } + + if len(v) == 0 { + return + } + + b.Reserve(len(v)) + arrow.Uint8Traits.Copy(b.rawData[b.length:], v) + b.builder.unsafeAppendBoolsToBitmap(valid, len(v)) +} + +func (b *Uint8Builder) init(capacity int) { + b.builder.init(capacity) + + b.data = memory.NewResizableBuffer(b.mem) + bytesN := arrow.Uint8Traits.BytesRequired(capacity) + b.data.Resize(bytesN) + b.rawData = arrow.Uint8Traits.CastFromBytes(b.data.Bytes()) +} + +// Reserve ensures there is enough space for appending n elements +// by checking the capacity and calling Resize if necessary. +func (b *Uint8Builder) Reserve(n int) { + b.builder.reserve(n, b.Resize) +} + +// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(), +// additional memory will be allocated. If n is smaller, the allocated memory may reduced. +func (b *Uint8Builder) Resize(n int) { + nBuilder := n + if n < minBuilderCapacity { + n = minBuilderCapacity + } + + if b.capacity == 0 { + b.init(n) + } else { + b.builder.resize(nBuilder, b.init) + b.data.Resize(arrow.Uint8Traits.BytesRequired(n)) + b.rawData = arrow.Uint8Traits.CastFromBytes(b.data.Bytes()) + } +} + +func (b *Uint8Builder) Value(i int) uint8 { + return b.rawData[i] +} + +// NewArray creates a Uint8 array from the memory buffers used by the builder and resets the Uint8Builder +// so it can be used to build a new array. +func (b *Uint8Builder) NewArray() arrow.Array { + return b.NewUint8Array() +} + +// NewUint8Array creates a Uint8 array from the memory buffers used by the builder and resets the Uint8Builder +// so it can be used to build a new array. +func (b *Uint8Builder) NewUint8Array() (a *Uint8) { + data := b.newData() + a = NewUint8Data(data) + data.Release() + return +} + +func (b *Uint8Builder) newData() (data *Data) { + bytesRequired := arrow.Uint8Traits.BytesRequired(b.length) + if bytesRequired > 0 && bytesRequired < b.data.Len() { + // trim buffers + b.data.Resize(bytesRequired) + } + data = NewData(arrow.PrimitiveTypes.Uint8, b.length, []*memory.Buffer{b.nullBitmap, b.data}, nil, b.nulls, 0) + b.reset() + + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + + return +} + +func (b *Uint8Builder) AppendValueFromString(s string) error { + if s == NullValueStr { + b.AppendNull() + return nil + } + v, err := strconv.ParseUint(s, 10, 1*8) + if err != nil { + b.AppendNull() + return err + } + b.Append(uint8(v)) + return nil +} + +func (b *Uint8Builder) UnmarshalOne(dec *json.Decoder) error { + t, err := dec.Token() + if err != nil { + return err + } + + switch v := t.(type) { + case nil: + b.AppendNull() + + case string: + f, err := strconv.ParseUint(v, 10, 1*8) + if err != nil { + return &json.UnmarshalTypeError{ + Value: v, + Type: reflect.TypeOf(uint8(0)), + Offset: dec.InputOffset(), + } + } + b.Append(uint8(f)) + case float64: + b.Append(uint8(v)) + case json.Number: + f, err := strconv.ParseUint(v.String(), 10, 1*8) + if err != nil { + return &json.UnmarshalTypeError{ + Value: v.String(), + Type: reflect.TypeOf(uint8(0)), + Offset: dec.InputOffset(), + } + } + b.Append(uint8(f)) + + default: + return &json.UnmarshalTypeError{ + Value: fmt.Sprint(t), + Type: reflect.TypeOf(uint8(0)), + Offset: dec.InputOffset(), + } + } + + return nil +} + +func (b *Uint8Builder) Unmarshal(dec *json.Decoder) error { + for dec.More() { + if err := b.UnmarshalOne(dec); err != nil { + return err + } + } + return nil +} + +func (b *Uint8Builder) UnmarshalJSON(data []byte) error { + dec := json.NewDecoder(bytes.NewReader(data)) + t, err := dec.Token() + if err != nil { + return err + } + + if delim, ok := t.(json.Delim); !ok || delim != '[' { + return fmt.Errorf("binary builder must unpack from json array, found %s", delim) + } + + return b.Unmarshal(dec) +} + +type Time32Builder struct { + builder + + dtype *arrow.Time32Type + data *memory.Buffer + rawData []arrow.Time32 +} + +func NewTime32Builder(mem memory.Allocator, dtype *arrow.Time32Type) *Time32Builder { + return &Time32Builder{builder: builder{refCount: 1, mem: mem}, dtype: dtype} +} + +func (b *Time32Builder) Type() arrow.DataType { return b.dtype } + +// Release decreases the reference count by 1. +// When the reference count goes to zero, the memory is freed. +func (b *Time32Builder) Release() { + debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases") + + if atomic.AddInt64(&b.refCount, -1) == 0 { + if b.nullBitmap != nil { + b.nullBitmap.Release() + b.nullBitmap = nil + } + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + } +} + +func (b *Time32Builder) Append(v arrow.Time32) { + b.Reserve(1) + b.UnsafeAppend(v) +} + +func (b *Time32Builder) AppendNull() { + b.Reserve(1) + b.UnsafeAppendBoolToBitmap(false) +} + +func (b *Time32Builder) AppendNulls(n int) { + for i := 0; i < n; i++ { + b.AppendNull() + } +} + +func (b *Time32Builder) AppendEmptyValue() { + b.Append(0) +} + +func (b *Time32Builder) AppendEmptyValues(n int) { + for i := 0; i < n; i++ { + b.AppendEmptyValue() + } +} + +func (b *Time32Builder) UnsafeAppend(v arrow.Time32) { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + b.rawData[b.length] = v + b.length++ +} + +func (b *Time32Builder) UnsafeAppendBoolToBitmap(isValid bool) { + if isValid { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + } else { + b.nulls++ + } + b.length++ +} + +// AppendValues will append the values in the v slice. The valid slice determines which values +// in v are valid (not null). The valid slice must either be empty or be equal in length to v. If empty, +// all values in v are appended and considered valid. +func (b *Time32Builder) AppendValues(v []arrow.Time32, valid []bool) { + if len(v) != len(valid) && len(valid) != 0 { + panic("len(v) != len(valid) && len(valid) != 0") + } + + if len(v) == 0 { + return + } + + b.Reserve(len(v)) + arrow.Time32Traits.Copy(b.rawData[b.length:], v) + b.builder.unsafeAppendBoolsToBitmap(valid, len(v)) +} + +func (b *Time32Builder) init(capacity int) { + b.builder.init(capacity) + + b.data = memory.NewResizableBuffer(b.mem) + bytesN := arrow.Time32Traits.BytesRequired(capacity) + b.data.Resize(bytesN) + b.rawData = arrow.Time32Traits.CastFromBytes(b.data.Bytes()) +} + +// Reserve ensures there is enough space for appending n elements +// by checking the capacity and calling Resize if necessary. +func (b *Time32Builder) Reserve(n int) { + b.builder.reserve(n, b.Resize) +} + +// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(), +// additional memory will be allocated. If n is smaller, the allocated memory may reduced. +func (b *Time32Builder) Resize(n int) { + nBuilder := n + if n < minBuilderCapacity { + n = minBuilderCapacity + } + + if b.capacity == 0 { + b.init(n) + } else { + b.builder.resize(nBuilder, b.init) + b.data.Resize(arrow.Time32Traits.BytesRequired(n)) + b.rawData = arrow.Time32Traits.CastFromBytes(b.data.Bytes()) + } +} + +func (b *Time32Builder) Value(i int) arrow.Time32 { + return b.rawData[i] +} + +// NewArray creates a Time32 array from the memory buffers used by the builder and resets the Time32Builder +// so it can be used to build a new array. +func (b *Time32Builder) NewArray() arrow.Array { + return b.NewTime32Array() +} + +// NewTime32Array creates a Time32 array from the memory buffers used by the builder and resets the Time32Builder +// so it can be used to build a new array. +func (b *Time32Builder) NewTime32Array() (a *Time32) { + data := b.newData() + a = NewTime32Data(data) + data.Release() + return +} + +func (b *Time32Builder) newData() (data *Data) { + bytesRequired := arrow.Time32Traits.BytesRequired(b.length) + if bytesRequired > 0 && bytesRequired < b.data.Len() { + // trim buffers + b.data.Resize(bytesRequired) + } + data = NewData(b.dtype, b.length, []*memory.Buffer{b.nullBitmap, b.data}, nil, b.nulls, 0) + b.reset() + + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + + return +} + +func (b *Time32Builder) AppendValueFromString(s string) error { + if s == NullValueStr { + b.AppendNull() + return nil + } + val, err := arrow.Time32FromString(s, b.dtype.Unit) + if err != nil { + b.AppendNull() + return err + } + b.Append(val) + return nil +} + +func (b *Time32Builder) UnmarshalOne(dec *json.Decoder) error { + t, err := dec.Token() + if err != nil { + return err + } + + switch v := t.(type) { + case nil: + b.AppendNull() + case string: + tm, err := arrow.Time32FromString(v, b.dtype.Unit) + if err != nil { + return &json.UnmarshalTypeError{ + Value: v, + Type: reflect.TypeOf(arrow.Time32(0)), + Offset: dec.InputOffset(), + } + } + + b.Append(tm) + case json.Number: + n, err := v.Int64() + if err != nil { + return &json.UnmarshalTypeError{ + Value: v.String(), + Type: reflect.TypeOf(arrow.Time32(0)), + Offset: dec.InputOffset(), + } + } + b.Append(arrow.Time32(n)) + case float64: + b.Append(arrow.Time32(v)) + + default: + return &json.UnmarshalTypeError{ + Value: fmt.Sprint(t), + Type: reflect.TypeOf(arrow.Time32(0)), + Offset: dec.InputOffset(), + } + } + + return nil +} + +func (b *Time32Builder) Unmarshal(dec *json.Decoder) error { + for dec.More() { + if err := b.UnmarshalOne(dec); err != nil { + return err + } + } + return nil +} + +func (b *Time32Builder) UnmarshalJSON(data []byte) error { + dec := json.NewDecoder(bytes.NewReader(data)) + t, err := dec.Token() + if err != nil { + return err + } + + if delim, ok := t.(json.Delim); !ok || delim != '[' { + return fmt.Errorf("binary builder must unpack from json array, found %s", delim) + } + + return b.Unmarshal(dec) +} + +type Time64Builder struct { + builder + + dtype *arrow.Time64Type + data *memory.Buffer + rawData []arrow.Time64 +} + +func NewTime64Builder(mem memory.Allocator, dtype *arrow.Time64Type) *Time64Builder { + return &Time64Builder{builder: builder{refCount: 1, mem: mem}, dtype: dtype} +} + +func (b *Time64Builder) Type() arrow.DataType { return b.dtype } + +// Release decreases the reference count by 1. +// When the reference count goes to zero, the memory is freed. +func (b *Time64Builder) Release() { + debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases") + + if atomic.AddInt64(&b.refCount, -1) == 0 { + if b.nullBitmap != nil { + b.nullBitmap.Release() + b.nullBitmap = nil + } + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + } +} + +func (b *Time64Builder) Append(v arrow.Time64) { + b.Reserve(1) + b.UnsafeAppend(v) +} + +func (b *Time64Builder) AppendNull() { + b.Reserve(1) + b.UnsafeAppendBoolToBitmap(false) +} + +func (b *Time64Builder) AppendNulls(n int) { + for i := 0; i < n; i++ { + b.AppendNull() + } +} + +func (b *Time64Builder) AppendEmptyValue() { + b.Append(0) +} + +func (b *Time64Builder) AppendEmptyValues(n int) { + for i := 0; i < n; i++ { + b.AppendEmptyValue() + } +} + +func (b *Time64Builder) UnsafeAppend(v arrow.Time64) { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + b.rawData[b.length] = v + b.length++ +} + +func (b *Time64Builder) UnsafeAppendBoolToBitmap(isValid bool) { + if isValid { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + } else { + b.nulls++ + } + b.length++ +} + +// AppendValues will append the values in the v slice. The valid slice determines which values +// in v are valid (not null). The valid slice must either be empty or be equal in length to v. If empty, +// all values in v are appended and considered valid. +func (b *Time64Builder) AppendValues(v []arrow.Time64, valid []bool) { + if len(v) != len(valid) && len(valid) != 0 { + panic("len(v) != len(valid) && len(valid) != 0") + } + + if len(v) == 0 { + return + } + + b.Reserve(len(v)) + arrow.Time64Traits.Copy(b.rawData[b.length:], v) + b.builder.unsafeAppendBoolsToBitmap(valid, len(v)) +} + +func (b *Time64Builder) init(capacity int) { + b.builder.init(capacity) + + b.data = memory.NewResizableBuffer(b.mem) + bytesN := arrow.Time64Traits.BytesRequired(capacity) + b.data.Resize(bytesN) + b.rawData = arrow.Time64Traits.CastFromBytes(b.data.Bytes()) +} + +// Reserve ensures there is enough space for appending n elements +// by checking the capacity and calling Resize if necessary. +func (b *Time64Builder) Reserve(n int) { + b.builder.reserve(n, b.Resize) +} + +// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(), +// additional memory will be allocated. If n is smaller, the allocated memory may reduced. +func (b *Time64Builder) Resize(n int) { + nBuilder := n + if n < minBuilderCapacity { + n = minBuilderCapacity + } + + if b.capacity == 0 { + b.init(n) + } else { + b.builder.resize(nBuilder, b.init) + b.data.Resize(arrow.Time64Traits.BytesRequired(n)) + b.rawData = arrow.Time64Traits.CastFromBytes(b.data.Bytes()) + } +} + +func (b *Time64Builder) Value(i int) arrow.Time64 { + return b.rawData[i] +} + +// NewArray creates a Time64 array from the memory buffers used by the builder and resets the Time64Builder +// so it can be used to build a new array. +func (b *Time64Builder) NewArray() arrow.Array { + return b.NewTime64Array() +} + +// NewTime64Array creates a Time64 array from the memory buffers used by the builder and resets the Time64Builder +// so it can be used to build a new array. +func (b *Time64Builder) NewTime64Array() (a *Time64) { + data := b.newData() + a = NewTime64Data(data) + data.Release() + return +} + +func (b *Time64Builder) newData() (data *Data) { + bytesRequired := arrow.Time64Traits.BytesRequired(b.length) + if bytesRequired > 0 && bytesRequired < b.data.Len() { + // trim buffers + b.data.Resize(bytesRequired) + } + data = NewData(b.dtype, b.length, []*memory.Buffer{b.nullBitmap, b.data}, nil, b.nulls, 0) + b.reset() + + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + + return +} + +func (b *Time64Builder) AppendValueFromString(s string) error { + if s == NullValueStr { + b.AppendNull() + return nil + } + val, err := arrow.Time64FromString(s, b.dtype.Unit) + if err != nil { + b.AppendNull() + return err + } + b.Append(val) + return nil +} + +func (b *Time64Builder) UnmarshalOne(dec *json.Decoder) error { + t, err := dec.Token() + if err != nil { + return err + } + + switch v := t.(type) { + case nil: + b.AppendNull() + case string: + tm, err := arrow.Time64FromString(v, b.dtype.Unit) + if err != nil { + return &json.UnmarshalTypeError{ + Value: v, + Type: reflect.TypeOf(arrow.Time64(0)), + Offset: dec.InputOffset(), + } + } + + b.Append(tm) + case json.Number: + n, err := v.Int64() + if err != nil { + return &json.UnmarshalTypeError{ + Value: v.String(), + Type: reflect.TypeOf(arrow.Time64(0)), + Offset: dec.InputOffset(), + } + } + b.Append(arrow.Time64(n)) + case float64: + b.Append(arrow.Time64(v)) + + default: + return &json.UnmarshalTypeError{ + Value: fmt.Sprint(t), + Type: reflect.TypeOf(arrow.Time64(0)), + Offset: dec.InputOffset(), + } + } + + return nil +} + +func (b *Time64Builder) Unmarshal(dec *json.Decoder) error { + for dec.More() { + if err := b.UnmarshalOne(dec); err != nil { + return err + } + } + return nil +} + +func (b *Time64Builder) UnmarshalJSON(data []byte) error { + dec := json.NewDecoder(bytes.NewReader(data)) + t, err := dec.Token() + if err != nil { + return err + } + + if delim, ok := t.(json.Delim); !ok || delim != '[' { + return fmt.Errorf("binary builder must unpack from json array, found %s", delim) + } + + return b.Unmarshal(dec) +} + +type Date32Builder struct { + builder + + data *memory.Buffer + rawData []arrow.Date32 +} + +func NewDate32Builder(mem memory.Allocator) *Date32Builder { + return &Date32Builder{builder: builder{refCount: 1, mem: mem}} +} + +func (b *Date32Builder) Type() arrow.DataType { return arrow.PrimitiveTypes.Date32 } + +// Release decreases the reference count by 1. +// When the reference count goes to zero, the memory is freed. +func (b *Date32Builder) Release() { + debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases") + + if atomic.AddInt64(&b.refCount, -1) == 0 { + if b.nullBitmap != nil { + b.nullBitmap.Release() + b.nullBitmap = nil + } + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + } +} + +func (b *Date32Builder) Append(v arrow.Date32) { + b.Reserve(1) + b.UnsafeAppend(v) +} + +func (b *Date32Builder) AppendNull() { + b.Reserve(1) + b.UnsafeAppendBoolToBitmap(false) +} + +func (b *Date32Builder) AppendNulls(n int) { + for i := 0; i < n; i++ { + b.AppendNull() + } +} + +func (b *Date32Builder) AppendEmptyValue() { + b.Append(0) +} + +func (b *Date32Builder) AppendEmptyValues(n int) { + for i := 0; i < n; i++ { + b.AppendEmptyValue() + } +} + +func (b *Date32Builder) UnsafeAppend(v arrow.Date32) { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + b.rawData[b.length] = v + b.length++ +} + +func (b *Date32Builder) UnsafeAppendBoolToBitmap(isValid bool) { + if isValid { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + } else { + b.nulls++ + } + b.length++ +} + +// AppendValues will append the values in the v slice. The valid slice determines which values +// in v are valid (not null). The valid slice must either be empty or be equal in length to v. If empty, +// all values in v are appended and considered valid. +func (b *Date32Builder) AppendValues(v []arrow.Date32, valid []bool) { + if len(v) != len(valid) && len(valid) != 0 { + panic("len(v) != len(valid) && len(valid) != 0") + } + + if len(v) == 0 { + return + } + + b.Reserve(len(v)) + arrow.Date32Traits.Copy(b.rawData[b.length:], v) + b.builder.unsafeAppendBoolsToBitmap(valid, len(v)) +} + +func (b *Date32Builder) init(capacity int) { + b.builder.init(capacity) + + b.data = memory.NewResizableBuffer(b.mem) + bytesN := arrow.Date32Traits.BytesRequired(capacity) + b.data.Resize(bytesN) + b.rawData = arrow.Date32Traits.CastFromBytes(b.data.Bytes()) +} + +// Reserve ensures there is enough space for appending n elements +// by checking the capacity and calling Resize if necessary. +func (b *Date32Builder) Reserve(n int) { + b.builder.reserve(n, b.Resize) +} + +// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(), +// additional memory will be allocated. If n is smaller, the allocated memory may reduced. +func (b *Date32Builder) Resize(n int) { + nBuilder := n + if n < minBuilderCapacity { + n = minBuilderCapacity + } + + if b.capacity == 0 { + b.init(n) + } else { + b.builder.resize(nBuilder, b.init) + b.data.Resize(arrow.Date32Traits.BytesRequired(n)) + b.rawData = arrow.Date32Traits.CastFromBytes(b.data.Bytes()) + } +} + +func (b *Date32Builder) Value(i int) arrow.Date32 { + return b.rawData[i] +} + +// NewArray creates a Date32 array from the memory buffers used by the builder and resets the Date32Builder +// so it can be used to build a new array. +func (b *Date32Builder) NewArray() arrow.Array { + return b.NewDate32Array() +} + +// NewDate32Array creates a Date32 array from the memory buffers used by the builder and resets the Date32Builder +// so it can be used to build a new array. +func (b *Date32Builder) NewDate32Array() (a *Date32) { + data := b.newData() + a = NewDate32Data(data) + data.Release() + return +} + +func (b *Date32Builder) newData() (data *Data) { + bytesRequired := arrow.Date32Traits.BytesRequired(b.length) + if bytesRequired > 0 && bytesRequired < b.data.Len() { + // trim buffers + b.data.Resize(bytesRequired) + } + data = NewData(arrow.PrimitiveTypes.Date32, b.length, []*memory.Buffer{b.nullBitmap, b.data}, nil, b.nulls, 0) + b.reset() + + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + + return +} + +func (b *Date32Builder) AppendValueFromString(s string) error { + if s == NullValueStr { + b.AppendNull() + return nil + } + tm, err := time.Parse("2006-01-02", s) + if err != nil { + b.AppendNull() + return err + } + b.Append(arrow.Date32FromTime(tm)) + return nil +} + +func (b *Date32Builder) UnmarshalOne(dec *json.Decoder) error { + t, err := dec.Token() + if err != nil { + return err + } + + switch v := t.(type) { + case nil: + b.AppendNull() + case string: + tm, err := time.Parse("2006-01-02", v) + if err != nil { + return &json.UnmarshalTypeError{ + Value: v, + Type: reflect.TypeOf(arrow.Date32(0)), + Offset: dec.InputOffset(), + } + } + + b.Append(arrow.Date32FromTime(tm)) + case json.Number: + n, err := v.Int64() + if err != nil { + return &json.UnmarshalTypeError{ + Value: v.String(), + Type: reflect.TypeOf(arrow.Date32(0)), + Offset: dec.InputOffset(), + } + } + b.Append(arrow.Date32(n)) + case float64: + b.Append(arrow.Date32(v)) + + default: + return &json.UnmarshalTypeError{ + Value: fmt.Sprint(t), + Type: reflect.TypeOf(arrow.Date32(0)), + Offset: dec.InputOffset(), + } + } + + return nil +} + +func (b *Date32Builder) Unmarshal(dec *json.Decoder) error { + for dec.More() { + if err := b.UnmarshalOne(dec); err != nil { + return err + } + } + return nil +} + +func (b *Date32Builder) UnmarshalJSON(data []byte) error { + dec := json.NewDecoder(bytes.NewReader(data)) + t, err := dec.Token() + if err != nil { + return err + } + + if delim, ok := t.(json.Delim); !ok || delim != '[' { + return fmt.Errorf("binary builder must unpack from json array, found %s", delim) + } + + return b.Unmarshal(dec) +} + +type Date64Builder struct { + builder + + data *memory.Buffer + rawData []arrow.Date64 +} + +func NewDate64Builder(mem memory.Allocator) *Date64Builder { + return &Date64Builder{builder: builder{refCount: 1, mem: mem}} +} + +func (b *Date64Builder) Type() arrow.DataType { return arrow.PrimitiveTypes.Date64 } + +// Release decreases the reference count by 1. +// When the reference count goes to zero, the memory is freed. +func (b *Date64Builder) Release() { + debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases") + + if atomic.AddInt64(&b.refCount, -1) == 0 { + if b.nullBitmap != nil { + b.nullBitmap.Release() + b.nullBitmap = nil + } + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + } +} + +func (b *Date64Builder) Append(v arrow.Date64) { + b.Reserve(1) + b.UnsafeAppend(v) +} + +func (b *Date64Builder) AppendNull() { + b.Reserve(1) + b.UnsafeAppendBoolToBitmap(false) +} + +func (b *Date64Builder) AppendNulls(n int) { + for i := 0; i < n; i++ { + b.AppendNull() + } +} + +func (b *Date64Builder) AppendEmptyValue() { + b.Append(0) +} + +func (b *Date64Builder) AppendEmptyValues(n int) { + for i := 0; i < n; i++ { + b.AppendEmptyValue() + } +} + +func (b *Date64Builder) UnsafeAppend(v arrow.Date64) { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + b.rawData[b.length] = v + b.length++ +} + +func (b *Date64Builder) UnsafeAppendBoolToBitmap(isValid bool) { + if isValid { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + } else { + b.nulls++ + } + b.length++ +} + +// AppendValues will append the values in the v slice. The valid slice determines which values +// in v are valid (not null). The valid slice must either be empty or be equal in length to v. If empty, +// all values in v are appended and considered valid. +func (b *Date64Builder) AppendValues(v []arrow.Date64, valid []bool) { + if len(v) != len(valid) && len(valid) != 0 { + panic("len(v) != len(valid) && len(valid) != 0") + } + + if len(v) == 0 { + return + } + + b.Reserve(len(v)) + arrow.Date64Traits.Copy(b.rawData[b.length:], v) + b.builder.unsafeAppendBoolsToBitmap(valid, len(v)) +} + +func (b *Date64Builder) init(capacity int) { + b.builder.init(capacity) + + b.data = memory.NewResizableBuffer(b.mem) + bytesN := arrow.Date64Traits.BytesRequired(capacity) + b.data.Resize(bytesN) + b.rawData = arrow.Date64Traits.CastFromBytes(b.data.Bytes()) +} + +// Reserve ensures there is enough space for appending n elements +// by checking the capacity and calling Resize if necessary. +func (b *Date64Builder) Reserve(n int) { + b.builder.reserve(n, b.Resize) +} + +// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(), +// additional memory will be allocated. If n is smaller, the allocated memory may reduced. +func (b *Date64Builder) Resize(n int) { + nBuilder := n + if n < minBuilderCapacity { + n = minBuilderCapacity + } + + if b.capacity == 0 { + b.init(n) + } else { + b.builder.resize(nBuilder, b.init) + b.data.Resize(arrow.Date64Traits.BytesRequired(n)) + b.rawData = arrow.Date64Traits.CastFromBytes(b.data.Bytes()) + } +} + +func (b *Date64Builder) Value(i int) arrow.Date64 { + return b.rawData[i] +} + +// NewArray creates a Date64 array from the memory buffers used by the builder and resets the Date64Builder +// so it can be used to build a new array. +func (b *Date64Builder) NewArray() arrow.Array { + return b.NewDate64Array() +} + +// NewDate64Array creates a Date64 array from the memory buffers used by the builder and resets the Date64Builder +// so it can be used to build a new array. +func (b *Date64Builder) NewDate64Array() (a *Date64) { + data := b.newData() + a = NewDate64Data(data) + data.Release() + return +} + +func (b *Date64Builder) newData() (data *Data) { + bytesRequired := arrow.Date64Traits.BytesRequired(b.length) + if bytesRequired > 0 && bytesRequired < b.data.Len() { + // trim buffers + b.data.Resize(bytesRequired) + } + data = NewData(arrow.PrimitiveTypes.Date64, b.length, []*memory.Buffer{b.nullBitmap, b.data}, nil, b.nulls, 0) + b.reset() + + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + + return +} + +func (b *Date64Builder) AppendValueFromString(s string) error { + if s == NullValueStr { + b.AppendNull() + return nil + } + tm, err := time.Parse("2006-01-02", s) + if err != nil { + b.AppendNull() + return err + } + b.Append(arrow.Date64FromTime(tm)) + return nil +} + +func (b *Date64Builder) UnmarshalOne(dec *json.Decoder) error { + t, err := dec.Token() + if err != nil { + return err + } + + switch v := t.(type) { + case nil: + b.AppendNull() + case string: + tm, err := time.Parse("2006-01-02", v) + if err != nil { + return &json.UnmarshalTypeError{ + Value: v, + Type: reflect.TypeOf(arrow.Date64(0)), + Offset: dec.InputOffset(), + } + } + + b.Append(arrow.Date64FromTime(tm)) + case json.Number: + n, err := v.Int64() + if err != nil { + return &json.UnmarshalTypeError{ + Value: v.String(), + Type: reflect.TypeOf(arrow.Date64(0)), + Offset: dec.InputOffset(), + } + } + b.Append(arrow.Date64(n)) + case float64: + b.Append(arrow.Date64(v)) + + default: + return &json.UnmarshalTypeError{ + Value: fmt.Sprint(t), + Type: reflect.TypeOf(arrow.Date64(0)), + Offset: dec.InputOffset(), + } + } + + return nil +} + +func (b *Date64Builder) Unmarshal(dec *json.Decoder) error { + for dec.More() { + if err := b.UnmarshalOne(dec); err != nil { + return err + } + } + return nil +} + +func (b *Date64Builder) UnmarshalJSON(data []byte) error { + dec := json.NewDecoder(bytes.NewReader(data)) + t, err := dec.Token() + if err != nil { + return err + } + + if delim, ok := t.(json.Delim); !ok || delim != '[' { + return fmt.Errorf("binary builder must unpack from json array, found %s", delim) + } + + return b.Unmarshal(dec) +} + +type DurationBuilder struct { + builder + + dtype *arrow.DurationType + data *memory.Buffer + rawData []arrow.Duration +} + +func NewDurationBuilder(mem memory.Allocator, dtype *arrow.DurationType) *DurationBuilder { + return &DurationBuilder{builder: builder{refCount: 1, mem: mem}, dtype: dtype} +} + +func (b *DurationBuilder) Type() arrow.DataType { return b.dtype } + +// Release decreases the reference count by 1. +// When the reference count goes to zero, the memory is freed. +func (b *DurationBuilder) Release() { + debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases") + + if atomic.AddInt64(&b.refCount, -1) == 0 { + if b.nullBitmap != nil { + b.nullBitmap.Release() + b.nullBitmap = nil + } + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + } +} + +func (b *DurationBuilder) Append(v arrow.Duration) { + b.Reserve(1) + b.UnsafeAppend(v) +} + +func (b *DurationBuilder) AppendNull() { + b.Reserve(1) + b.UnsafeAppendBoolToBitmap(false) +} + +func (b *DurationBuilder) AppendNulls(n int) { + for i := 0; i < n; i++ { + b.AppendNull() + } +} + +func (b *DurationBuilder) AppendEmptyValue() { + b.Append(0) +} + +func (b *DurationBuilder) AppendEmptyValues(n int) { + for i := 0; i < n; i++ { + b.AppendEmptyValue() + } +} + +func (b *DurationBuilder) UnsafeAppend(v arrow.Duration) { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + b.rawData[b.length] = v + b.length++ +} + +func (b *DurationBuilder) UnsafeAppendBoolToBitmap(isValid bool) { + if isValid { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + } else { + b.nulls++ + } + b.length++ +} + +// AppendValues will append the values in the v slice. The valid slice determines which values +// in v are valid (not null). The valid slice must either be empty or be equal in length to v. If empty, +// all values in v are appended and considered valid. +func (b *DurationBuilder) AppendValues(v []arrow.Duration, valid []bool) { + if len(v) != len(valid) && len(valid) != 0 { + panic("len(v) != len(valid) && len(valid) != 0") + } + + if len(v) == 0 { + return + } + + b.Reserve(len(v)) + arrow.DurationTraits.Copy(b.rawData[b.length:], v) + b.builder.unsafeAppendBoolsToBitmap(valid, len(v)) +} + +func (b *DurationBuilder) init(capacity int) { + b.builder.init(capacity) + + b.data = memory.NewResizableBuffer(b.mem) + bytesN := arrow.DurationTraits.BytesRequired(capacity) + b.data.Resize(bytesN) + b.rawData = arrow.DurationTraits.CastFromBytes(b.data.Bytes()) +} + +// Reserve ensures there is enough space for appending n elements +// by checking the capacity and calling Resize if necessary. +func (b *DurationBuilder) Reserve(n int) { + b.builder.reserve(n, b.Resize) +} + +// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(), +// additional memory will be allocated. If n is smaller, the allocated memory may reduced. +func (b *DurationBuilder) Resize(n int) { + nBuilder := n + if n < minBuilderCapacity { + n = minBuilderCapacity + } + + if b.capacity == 0 { + b.init(n) + } else { + b.builder.resize(nBuilder, b.init) + b.data.Resize(arrow.DurationTraits.BytesRequired(n)) + b.rawData = arrow.DurationTraits.CastFromBytes(b.data.Bytes()) + } +} + +func (b *DurationBuilder) Value(i int) arrow.Duration { + return b.rawData[i] +} + +// NewArray creates a Duration array from the memory buffers used by the builder and resets the DurationBuilder +// so it can be used to build a new array. +func (b *DurationBuilder) NewArray() arrow.Array { + return b.NewDurationArray() +} + +// NewDurationArray creates a Duration array from the memory buffers used by the builder and resets the DurationBuilder +// so it can be used to build a new array. +func (b *DurationBuilder) NewDurationArray() (a *Duration) { + data := b.newData() + a = NewDurationData(data) + data.Release() + return +} + +func (b *DurationBuilder) newData() (data *Data) { + bytesRequired := arrow.DurationTraits.BytesRequired(b.length) + if bytesRequired > 0 && bytesRequired < b.data.Len() { + // trim buffers + b.data.Resize(bytesRequired) + } + data = NewData(b.dtype, b.length, []*memory.Buffer{b.nullBitmap, b.data}, nil, b.nulls, 0) + b.reset() + + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + + return +} + +func (b *DurationBuilder) AppendValueFromString(s string) error { + if s == NullValueStr { + b.AppendNull() + return nil + } + dur, err := time.ParseDuration(s) + if err != nil { + return err + } + + b.Append(arrow.Duration(dur / b.dtype.Unit.Multiplier())) + return nil +} + +func (b *DurationBuilder) UnmarshalOne(dec *json.Decoder) error { + t, err := dec.Token() + if err != nil { + return err + } + + switch v := t.(type) { + case nil: + b.AppendNull() + case json.Number: + n, err := v.Int64() + if err != nil { + return &json.UnmarshalTypeError{ + Value: v.String(), + Type: reflect.TypeOf(arrow.Duration(0)), + Offset: dec.InputOffset(), + } + } + b.Append(arrow.Duration(n)) + case float64: + b.Append(arrow.Duration(v)) + case string: + // be flexible for specifying durations by accepting forms like + // 3h2m0.5s regardless of the unit and converting it to the proper + // precision. + val, err := time.ParseDuration(v) + if err != nil { + // if we got an error, maybe it was because the attempt to create + // a time.Duration (int64) in nanoseconds would overflow. check if + // the string is just a large number followed by the unit suffix + if strings.HasSuffix(v, b.dtype.Unit.String()) { + value, err := strconv.ParseInt(v[:len(v)-len(b.dtype.Unit.String())], 10, 64) + if err == nil { + b.Append(arrow.Duration(value)) + break + } + } + + return &json.UnmarshalTypeError{ + Value: v, + Type: reflect.TypeOf(arrow.Duration(0)), + Offset: dec.InputOffset(), + } + } + + switch b.dtype.Unit { + case arrow.Nanosecond: + b.Append(arrow.Duration(val.Nanoseconds())) + case arrow.Microsecond: + b.Append(arrow.Duration(val.Microseconds())) + case arrow.Millisecond: + b.Append(arrow.Duration(val.Milliseconds())) + case arrow.Second: + b.Append(arrow.Duration(val.Seconds())) + } + + default: + return &json.UnmarshalTypeError{ + Value: fmt.Sprint(t), + Type: reflect.TypeOf(arrow.Duration(0)), + Offset: dec.InputOffset(), + } + } + + return nil +} + +func (b *DurationBuilder) Unmarshal(dec *json.Decoder) error { + for dec.More() { + if err := b.UnmarshalOne(dec); err != nil { + return err + } + } + return nil +} + +func (b *DurationBuilder) UnmarshalJSON(data []byte) error { + dec := json.NewDecoder(bytes.NewReader(data)) + t, err := dec.Token() + if err != nil { + return err + } + + if delim, ok := t.(json.Delim); !ok || delim != '[' { + return fmt.Errorf("binary builder must unpack from json array, found %s", delim) + } + + return b.Unmarshal(dec) +} + +var ( + _ Builder = (*Int64Builder)(nil) + _ Builder = (*Uint64Builder)(nil) + _ Builder = (*Float64Builder)(nil) + _ Builder = (*Int32Builder)(nil) + _ Builder = (*Uint32Builder)(nil) + _ Builder = (*Float32Builder)(nil) + _ Builder = (*Int16Builder)(nil) + _ Builder = (*Uint16Builder)(nil) + _ Builder = (*Int8Builder)(nil) + _ Builder = (*Uint8Builder)(nil) + _ Builder = (*Time32Builder)(nil) + _ Builder = (*Time64Builder)(nil) + _ Builder = (*Date32Builder)(nil) + _ Builder = (*Date64Builder)(nil) + _ Builder = (*DurationBuilder)(nil) +) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array/numericbuilder.gen.go.tmpl b/vendor/github.com/apache/arrow/go/v14/arrow/array/numericbuilder.gen.go.tmpl new file mode 100644 index 000000000..cf663c031 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array/numericbuilder.gen.go.tmpl @@ -0,0 +1,447 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package array + +import ( + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/bitutil" + "github.com/apache/arrow/go/v14/arrow/internal/debug" + "github.com/apache/arrow/go/v14/arrow/memory" + "github.com/apache/arrow/go/v14/internal/json" +) + +{{range .In}} + +type {{.Name}}Builder struct { + builder + +{{if .Opt.Parametric -}} + dtype *arrow.{{.Name}}Type +{{end -}} + data *memory.Buffer + rawData []{{or .QualifiedType .Type}} +} + +{{if .Opt.Parametric}} +func New{{.Name}}Builder(mem memory.Allocator, dtype *arrow.{{.Name}}Type) *{{.Name}}Builder { + return &{{.Name}}Builder{builder: builder{refCount:1, mem: mem}, dtype: dtype} +} + +func (b *{{.Name}}Builder) Type() arrow.DataType { return b.dtype } + +{{else}} +func New{{.Name}}Builder(mem memory.Allocator) *{{.Name}}Builder { + return &{{.Name}}Builder{builder: builder{refCount:1, mem: mem}} +} + +func (b *{{.Name}}Builder) Type() arrow.DataType { return arrow.PrimitiveTypes.{{.Name}} } +{{end}} + +// Release decreases the reference count by 1. +// When the reference count goes to zero, the memory is freed. +func (b *{{.Name}}Builder) Release() { + debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases") + + if atomic.AddInt64(&b.refCount, -1) == 0 { + if b.nullBitmap != nil { + b.nullBitmap.Release() + b.nullBitmap = nil + } + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + } +} + +func (b *{{.Name}}Builder) Append(v {{or .QualifiedType .Type}}) { + b.Reserve(1) + b.UnsafeAppend(v) +} + +func (b *{{.Name}}Builder) AppendNull() { + b.Reserve(1) + b.UnsafeAppendBoolToBitmap(false) +} + +func (b *{{.Name}}Builder) AppendNulls(n int) { + for i := 0; i < n; i++ { + b.AppendNull() + } +} + +func (b *{{.Name}}Builder) AppendEmptyValue() { + b.Append(0) +} + +func (b *{{.Name}}Builder) AppendEmptyValues(n int) { + for i := 0; i < n; i ++ { + b.AppendEmptyValue() + } +} + +func (b *{{.Name}}Builder) UnsafeAppend(v {{or .QualifiedType .Type}}) { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + b.rawData[b.length] = v + b.length++ +} + +func (b *{{.Name}}Builder) UnsafeAppendBoolToBitmap(isValid bool) { + if isValid { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + } else { + b.nulls++ + } + b.length++ +} + +// AppendValues will append the values in the v slice. The valid slice determines which values +// in v are valid (not null). The valid slice must either be empty or be equal in length to v. If empty, +// all values in v are appended and considered valid. +func (b *{{.Name}}Builder) AppendValues(v []{{or .QualifiedType .Type}}, valid []bool) { + if len(v) != len(valid) && len(valid) != 0 { + panic("len(v) != len(valid) && len(valid) != 0") + } + + if len(v) == 0 { + return + } + + b.Reserve(len(v)) + arrow.{{.Name}}Traits.Copy(b.rawData[b.length:], v) + b.builder.unsafeAppendBoolsToBitmap(valid, len(v)) +} + +func (b *{{.Name}}Builder) init(capacity int) { + b.builder.init(capacity) + + b.data = memory.NewResizableBuffer(b.mem) + bytesN := arrow.{{.Name}}Traits.BytesRequired(capacity) + b.data.Resize(bytesN) + b.rawData = arrow.{{.Name}}Traits.CastFromBytes(b.data.Bytes()) +} + +// Reserve ensures there is enough space for appending n elements +// by checking the capacity and calling Resize if necessary. +func (b *{{.Name}}Builder) Reserve(n int) { + b.builder.reserve(n, b.Resize) +} + +// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(), +// additional memory will be allocated. If n is smaller, the allocated memory may reduced. +func (b *{{.Name}}Builder) Resize(n int) { + nBuilder := n + if n < minBuilderCapacity { + n = minBuilderCapacity + } + + if b.capacity == 0 { + b.init(n) + } else { + b.builder.resize(nBuilder, b.init) + b.data.Resize(arrow.{{.Name}}Traits.BytesRequired(n)) + b.rawData = arrow.{{.Name}}Traits.CastFromBytes(b.data.Bytes()) + } +} + +func (b *{{.Name}}Builder) Value(i int) {{or .QualifiedType .Type}} { + return b.rawData[i] +} + +// NewArray creates a {{.Name}} array from the memory buffers used by the builder and resets the {{.Name}}Builder +// so it can be used to build a new array. +func (b *{{.Name}}Builder) NewArray() arrow.Array { + return b.New{{.Name}}Array() +} + +// New{{.Name}}Array creates a {{.Name}} array from the memory buffers used by the builder and resets the {{.Name}}Builder +// so it can be used to build a new array. +func (b *{{.Name}}Builder) New{{.Name}}Array() (a *{{.Name}}) { + data := b.newData() + a = New{{.Name}}Data(data) + data.Release() + return +} + +func (b *{{.Name}}Builder) newData() (data *Data) { + bytesRequired := arrow.{{.Name}}Traits.BytesRequired(b.length) + if bytesRequired > 0 && bytesRequired < b.data.Len() { + // trim buffers + b.data.Resize(bytesRequired) + } +{{if .Opt.Parametric -}} + data = NewData(b.dtype, b.length, []*memory.Buffer{b.nullBitmap, b.data}, nil, b.nulls, 0) +{{else -}} + data = NewData(arrow.PrimitiveTypes.{{.Name}}, b.length, []*memory.Buffer{b.nullBitmap, b.data}, nil, b.nulls, 0) +{{end -}} + b.reset() + + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + + return +} + +func (b *{{.Name}}Builder) AppendValueFromString(s string) error { + if s == NullValueStr { + b.AppendNull() + return nil + } + {{if or (eq .Name "Date32") -}} + tm, err := time.Parse("2006-01-02", s) + if err != nil { + b.AppendNull() + return err + } + b.Append(arrow.Date32FromTime(tm)) + {{else if or (eq .Name "Date64") -}} + tm, err := time.Parse("2006-01-02", s) + if err != nil { + b.AppendNull() + return err + } + b.Append(arrow.Date64FromTime(tm)) + {{else if or (eq .Name "Time32") -}} + val, err := arrow.Time32FromString(s, b.dtype.Unit) + if err != nil { + b.AppendNull() + return err + } + b.Append(val) + {{else if or (eq .Name "Time64") -}} + val, err := arrow.Time64FromString(s, b.dtype.Unit) + if err != nil { + b.AppendNull() + return err + } + b.Append(val) + {{else if (eq .Name "Duration") -}} + dur, err := time.ParseDuration(s) + if err != nil { + return err + } + + b.Append(arrow.Duration(dur / b.dtype.Unit.Multiplier())) + {{else if or (eq .Name "Int8") (eq .Name "Int16") (eq .Name "Int32") (eq .Name "Int64") -}} + v, err := strconv.ParseInt(s, 10, {{.Size}} * 8) + if err != nil { + b.AppendNull() + return err + } + b.Append({{.name}}(v)) + {{else if or (eq .Name "Uint8") (eq .Name "Uint16") (eq .Name "Uint32") (eq .Name "Uint64") -}} + v, err := strconv.ParseUint(s, 10, {{.Size}} * 8) + if err != nil { + b.AppendNull() + return err + } + b.Append({{.name}}(v)) + {{else if or (eq .Name "Float32") (eq .Name "Float64") -}} + v, err := strconv.ParseFloat(s, {{.Size}} * 8) + if err != nil { + b.AppendNull() + return err + } + b.Append({{.name}}(v)) + {{end -}} + return nil +} + +func (b *{{.Name}}Builder) UnmarshalOne(dec *json.Decoder) error { + t, err := dec.Token() + if err != nil { + return err + } + + switch v := t.(type) { + case nil: + b.AppendNull() +{{if or (eq .Name "Date32") (eq .Name "Date64") -}} + case string: + tm, err := time.Parse("2006-01-02", v) + if err != nil { + return &json.UnmarshalTypeError{ + Value: v, + Type: reflect.TypeOf({{.QualifiedType}}(0)), + Offset: dec.InputOffset(), + } + } + + b.Append({{.QualifiedType}}FromTime(tm)) + case json.Number: + n, err := v.Int64() + if err != nil { + return &json.UnmarshalTypeError{ + Value: v.String(), + Type: reflect.TypeOf({{.QualifiedType}}(0)), + Offset: dec.InputOffset(), + } + } + b.Append({{.QualifiedType}}(n)) + case float64: + b.Append({{.QualifiedType}}(v)) +{{else if or (eq .Name "Time32") (eq .Name "Time64") -}} + case string: + tm, err := {{.QualifiedType}}FromString(v, b.dtype.Unit) + if err != nil { + return &json.UnmarshalTypeError{ + Value: v, + Type: reflect.TypeOf({{.QualifiedType}}(0)), + Offset: dec.InputOffset(), + } + } + + b.Append(tm) + case json.Number: + n, err := v.Int64() + if err != nil { + return &json.UnmarshalTypeError{ + Value: v.String(), + Type: reflect.TypeOf({{.QualifiedType}}(0)), + Offset: dec.InputOffset(), + } + } + b.Append({{.QualifiedType}}(n)) + case float64: + b.Append({{.QualifiedType}}(v)) +{{else if eq .Name "Duration" -}} + case json.Number: + n, err := v.Int64() + if err != nil { + return &json.UnmarshalTypeError{ + Value: v.String(), + Type: reflect.TypeOf({{.QualifiedType}}(0)), + Offset: dec.InputOffset(), + } + } + b.Append({{.QualifiedType}}(n)) + case float64: + b.Append({{.QualifiedType}}(v)) + case string: + // be flexible for specifying durations by accepting forms like + // 3h2m0.5s regardless of the unit and converting it to the proper + // precision. + val, err := time.ParseDuration(v) + if err != nil { + // if we got an error, maybe it was because the attempt to create + // a time.Duration (int64) in nanoseconds would overflow. check if + // the string is just a large number followed by the unit suffix + if strings.HasSuffix(v, b.dtype.Unit.String()) { + value, err := strconv.ParseInt(v[:len(v)-len(b.dtype.Unit.String())], 10, 64) + if err == nil { + b.Append(arrow.Duration(value)) + break + } + } + + return &json.UnmarshalTypeError{ + Value: v, + Type: reflect.TypeOf({{.QualifiedType}}(0)), + Offset: dec.InputOffset(), + } + } + + switch b.dtype.Unit { + case arrow.Nanosecond: + b.Append({{.QualifiedType}}(val.Nanoseconds())) + case arrow.Microsecond: + b.Append({{.QualifiedType}}(val.Microseconds())) + case arrow.Millisecond: + b.Append({{.QualifiedType}}(val.Milliseconds())) + case arrow.Second: + b.Append({{.QualifiedType}}(val.Seconds())) + } +{{else}} + case string: +{{if or (eq .Name "Float32") (eq .Name "Float64") -}} + f, err := strconv.ParseFloat(v, {{.Size}}*8) +{{else if eq (printf "%.1s" .Name) "U" -}} + f, err := strconv.ParseUint(v, 10, {{.Size}}*8) +{{else -}} + f, err := strconv.ParseInt(v, 10, {{.Size}}*8) +{{end -}} + if err != nil { + return &json.UnmarshalTypeError{ + Value: v, + Type: reflect.TypeOf({{.name}}(0)), + Offset: dec.InputOffset(), + } + } + b.Append({{.name}}(f)) + case float64: + b.Append({{.name}}(v)) + case json.Number: +{{if or (eq .Name "Float32") (eq .Name "Float64") -}} + f, err := strconv.ParseFloat(v.String(), {{.Size}}*8) +{{else if eq (printf "%.1s" .Name) "U" -}} + f, err := strconv.ParseUint(v.String(), 10, {{.Size}}*8) +{{else -}} + f, err := strconv.ParseInt(v.String(), 10, {{.Size}}*8) +{{end -}} + if err != nil { + return &json.UnmarshalTypeError{ + Value: v.String(), + Type: reflect.TypeOf({{.name}}(0)), + Offset: dec.InputOffset(), + } + } + b.Append({{.name}}(f)) +{{end}} + default: + return &json.UnmarshalTypeError{ + Value: fmt.Sprint(t), + Type: reflect.TypeOf({{or .QualifiedType .Type}}(0)), + Offset: dec.InputOffset(), + } + } + + return nil +} + +func (b *{{.Name}}Builder) Unmarshal(dec *json.Decoder) error { + for dec.More() { + if err := b.UnmarshalOne(dec); err != nil { + return err + } + } + return nil +} + +func (b *{{.Name}}Builder) UnmarshalJSON(data []byte) error { + dec := json.NewDecoder(bytes.NewReader(data)) + t, err := dec.Token() + if err != nil { + return err + } + + if delim, ok := t.(json.Delim); !ok || delim != '[' { + return fmt.Errorf("binary builder must unpack from json array, found %s", delim) + } + + return b.Unmarshal(dec) +} +{{end}} + +var ( +{{- range .In}} + _ Builder = (*{{.Name}}Builder)(nil) +{{- end}} +) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array/numericbuilder.gen_test.go.tmpl b/vendor/github.com/apache/arrow/go/v14/arrow/array/numericbuilder.gen_test.go.tmpl new file mode 100644 index 000000000..bc8c99337 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array/numericbuilder.gen_test.go.tmpl @@ -0,0 +1,276 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package array_test + +import ( + "testing" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/array" + "github.com/apache/arrow/go/v14/arrow/memory" + "github.com/stretchr/testify/assert" +) + +{{range .In}} +func Test{{.Name}}StringRoundTrip(t *testing.T) { + // 1. create array + mem := memory.NewCheckedAllocator(memory.NewGoAllocator()) + defer mem.AssertSize(t, 0) + +{{if .Opt.Parametric -}} +{{ if or (eq .Name "Time64") -}} + dt := &arrow.{{.Name}}Type{Unit: arrow.Microsecond} +{{else -}} + dt := &arrow.{{.Name}}Type{Unit: arrow.Second} +{{end -}} + b := array.New{{.Name}}Builder(mem, dt) +{{else -}} + b := array.New{{.Name}}Builder(mem) +{{end -}} + defer b.Release() + + b.Append(1) + b.Append(2) + b.Append(3) + b.AppendNull() + b.Append(5) + b.Append(6) + b.AppendNull() + b.Append(8) + b.Append(9) + b.Append(10) + + arr := b.NewArray().(*array.{{.Name}}) + defer arr.Release() + + // 2. create array via AppendValueFromString +{{if .Opt.Parametric -}} + b1 := array.New{{.Name}}Builder(mem, dt) +{{else -}} + b1 := array.New{{.Name}}Builder(mem) +{{end -}} + defer b1.Release() + + for i := 0; i < arr.Len(); i++ { + assert.NoError(t, b1.AppendValueFromString(arr.ValueStr(i))) + } + + arr1 := b1.NewArray().(*array.{{.Name}}) + defer arr1.Release() + +{{ if or (eq .Name "Date64") -}} + assert.Exactly(t, arr.Len(), arr1.Len()) + for i := 0; i < arr.Len(); i++ { + assert.Exactly(t, arr.IsValid(i), arr1.IsValid(i)) + assert.Exactly(t, arr.ValueStr(i), arr1.ValueStr(i)) + if arr.IsValid(i) { + assert.Exactly(t, arr.Value(i).ToTime(), arr1.Value(i).ToTime()) + } + } +{{else -}} + assert.True(t, array.Equal(arr, arr1)) +{{end -}} +} + +func TestNew{{.Name}}Builder(t *testing.T) { + mem := memory.NewCheckedAllocator(memory.NewGoAllocator()) + defer mem.AssertSize(t, 0) + +{{if .Opt.Parametric -}} + dtype := &arrow.{{.Name}}Type{Unit: arrow.Second} + ab := array.New{{.Name}}Builder(mem, dtype) +{{else}} + ab := array.New{{.Name}}Builder(mem) +{{end -}} + defer ab.Release() + + ab.Retain() + ab.Release() + + ab.Append(1) + ab.Append(2) + ab.Append(3) + ab.AppendNull() + ab.Append(5) + ab.Append(6) + ab.AppendNull() + ab.Append(8) + ab.Append(9) + ab.Append(10) + + // check state of builder before New{{.Name}}Array + assert.Equal(t, 10, ab.Len(), "unexpected Len()") + assert.Equal(t, 2, ab.NullN(), "unexpected NullN()") + + a := ab.New{{.Name}}Array() + + // check state of builder after New{{.Name}}Array + assert.Zero(t, ab.Len(), "unexpected ArrayBuilder.Len(), New{{.Name}}Array did not reset state") + assert.Zero(t, ab.Cap(), "unexpected ArrayBuilder.Cap(), New{{.Name}}Array did not reset state") + assert.Zero(t, ab.NullN(), "unexpected ArrayBuilder.NullN(), New{{.Name}}Array did not reset state") + + // check state of array + assert.Equal(t, 2, a.NullN(), "unexpected null count") + assert.Equal(t, []{{or .QualifiedType .Type}}{1, 2, 3, 0, 5, 6, 0, 8, 9, 10}, a.{{.Name}}Values(), "unexpected {{.Name}}Values") + assert.Equal(t, []byte{0xb7}, a.NullBitmapBytes()[:1]) // 4 bytes due to minBuilderCapacity + assert.Len(t, a.{{.Name}}Values(), 10, "unexpected length of {{.Name}}Values") + + a.Release() + + ab.Append(7) + ab.Append(8) + + a = ab.New{{.Name}}Array() + + assert.Equal(t, 0, a.NullN()) + assert.Equal(t, []{{or .QualifiedType .Type}}{7, 8}, a.{{.Name}}Values()) + assert.Len(t, a.{{.Name}}Values(), 2) + + a.Release() + + var ( + want = []{{or .QualifiedType .Type}}{1, 2, 3, 4} + valids = []bool{true, true, false, true} + ) + + ab.AppendValues(want, valids) + a = ab.New{{.Name}}Array() + + sub := array.MakeFromData(a.Data()) + defer sub.Release() + + if got, want := sub.DataType().ID(), a.DataType().ID(); got != want { + t.Fatalf("invalid type: got=%q, want=%q", got, want) + } + + if _, ok := sub.(*array.{{.Name}}); !ok { + t.Fatalf("could not type-assert to array.{{.Name}}") + } + + if got, want := a.String(), `[1 2 (null) 4]`; got != want { + t.Fatalf("got=%q, want=%q", got, want) + } + + slice := array.NewSliceData(a.Data(), 2, 4) + defer slice.Release() + + sub1 := array.MakeFromData(slice) + defer sub1.Release() + + v, ok := sub1.(*array.{{.Name}}) + if !ok { + t.Fatalf("could not type-assert to array.{{.Name}}") + } + + if got, want := v.String(), `[(null) 4]`; got != want { + t.Fatalf("got=%q, want=%q", got, want) + } + + a.Release() +} + +func Test{{.Name}}Builder_AppendValues(t *testing.T) { + mem := memory.NewCheckedAllocator(memory.NewGoAllocator()) + defer mem.AssertSize(t, 0) + +{{if .Opt.Parametric -}} + dtype := &arrow.{{.Name}}Type{Unit: arrow.Second} + ab := array.New{{.Name}}Builder(mem, dtype) +{{else}} + ab := array.New{{.Name}}Builder(mem) +{{end -}} + defer ab.Release() + + exp := []{{or .QualifiedType .Type}}{0, 1, 2, 3} + ab.AppendValues(exp, nil) + a := ab.New{{.Name}}Array() + assert.Equal(t, exp, a.{{.Name}}Values()) + + a.Release() +} + +func Test{{.Name}}Builder_Empty(t *testing.T) { + mem := memory.NewCheckedAllocator(memory.NewGoAllocator()) + defer mem.AssertSize(t, 0) + +{{if .Opt.Parametric -}} + dtype := &arrow.{{.Name}}Type{Unit: arrow.Second} + ab := array.New{{.Name}}Builder(mem, dtype) +{{else}} + ab := array.New{{.Name}}Builder(mem) +{{end -}} + defer ab.Release() + + exp := []{{or .QualifiedType .Type}}{0, 1, 2, 3} + + ab.AppendValues([]{{or .QualifiedType .Type}}{}, nil) + a := ab.New{{.Name}}Array() + assert.Zero(t, a.Len()) + a.Release() + + ab.AppendValues(nil, nil) + a = ab.New{{.Name}}Array() + assert.Zero(t, a.Len()) + a.Release() + + ab.AppendValues([]{{or .QualifiedType .Type}}{}, nil) + ab.AppendValues(exp, nil) + a = ab.New{{.Name}}Array() + assert.Equal(t, exp, a.{{.Name}}Values()) + a.Release() + + ab.AppendValues(exp, nil) + ab.AppendValues([]{{or .QualifiedType .Type}}{}, nil) + a = ab.New{{.Name}}Array() + assert.Equal(t, exp, a.{{.Name}}Values()) + a.Release() +} + +func Test{{.Name}}Builder_Resize(t *testing.T) { + mem := memory.NewCheckedAllocator(memory.NewGoAllocator()) + defer mem.AssertSize(t, 0) + +{{if .Opt.Parametric -}} + dtype := &arrow.{{.Name}}Type{Unit: arrow.Second} + ab := array.New{{.Name}}Builder(mem, dtype) +{{else}} + ab := array.New{{.Name}}Builder(mem) +{{end -}} + defer ab.Release() + + assert.Equal(t, 0, ab.Cap()) + assert.Equal(t, 0, ab.Len()) + + ab.Reserve(63) + assert.Equal(t, 64, ab.Cap()) + assert.Equal(t, 0, ab.Len()) + + for i := 0; i < 63; i++ { + ab.Append(0) + } + assert.Equal(t, 64, ab.Cap()) + assert.Equal(t, 63, ab.Len()) + + ab.Resize(5) + assert.Equal(t, 5, ab.Len()) + + ab.Resize(32) + assert.Equal(t, 5, ab.Len()) +} +{{end}} + + diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array/record.go b/vendor/github.com/apache/arrow/go/v14/arrow/array/record.go new file mode 100644 index 000000000..0b0fe4c38 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array/record.go @@ -0,0 +1,411 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package array + +import ( + "bytes" + "fmt" + "strings" + "sync/atomic" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/internal/debug" + "github.com/apache/arrow/go/v14/arrow/memory" + "github.com/apache/arrow/go/v14/internal/json" +) + +// RecordReader reads a stream of records. +type RecordReader interface { + Retain() + Release() + + Schema() *arrow.Schema + + Next() bool + Record() arrow.Record + Err() error +} + +// simpleRecords is a simple iterator over a collection of records. +type simpleRecords struct { + refCount int64 + + schema *arrow.Schema + recs []arrow.Record + cur arrow.Record +} + +// NewRecordReader returns a simple iterator over the given slice of records. +func NewRecordReader(schema *arrow.Schema, recs []arrow.Record) (*simpleRecords, error) { + rs := &simpleRecords{ + refCount: 1, + schema: schema, + recs: recs, + cur: nil, + } + + for _, rec := range rs.recs { + rec.Retain() + } + + for _, rec := range recs { + if !rec.Schema().Equal(rs.schema) { + rs.Release() + return nil, fmt.Errorf("arrow/array: mismatch schema") + } + } + + return rs, nil +} + +// Retain increases the reference count by 1. +// Retain may be called simultaneously from multiple goroutines. +func (rs *simpleRecords) Retain() { + atomic.AddInt64(&rs.refCount, 1) +} + +// Release decreases the reference count by 1. +// When the reference count goes to zero, the memory is freed. +// Release may be called simultaneously from multiple goroutines. +func (rs *simpleRecords) Release() { + debug.Assert(atomic.LoadInt64(&rs.refCount) > 0, "too many releases") + + if atomic.AddInt64(&rs.refCount, -1) == 0 { + if rs.cur != nil { + rs.cur.Release() + } + for _, rec := range rs.recs { + rec.Release() + } + rs.recs = nil + } +} + +func (rs *simpleRecords) Schema() *arrow.Schema { return rs.schema } +func (rs *simpleRecords) Record() arrow.Record { return rs.cur } +func (rs *simpleRecords) Next() bool { + if len(rs.recs) == 0 { + return false + } + if rs.cur != nil { + rs.cur.Release() + } + rs.cur = rs.recs[0] + rs.recs = rs.recs[1:] + return true +} +func (rs *simpleRecords) Err() error { return nil } + +// simpleRecord is a basic, non-lazy in-memory record batch. +type simpleRecord struct { + refCount int64 + + schema *arrow.Schema + + rows int64 + arrs []arrow.Array +} + +// NewRecord returns a basic, non-lazy in-memory record batch. +// +// NewRecord panics if the columns and schema are inconsistent. +// NewRecord panics if rows is larger than the height of the columns. +func NewRecord(schema *arrow.Schema, cols []arrow.Array, nrows int64) *simpleRecord { + rec := &simpleRecord{ + refCount: 1, + schema: schema, + rows: nrows, + arrs: make([]arrow.Array, len(cols)), + } + copy(rec.arrs, cols) + for _, arr := range rec.arrs { + arr.Retain() + } + + if rec.rows < 0 { + switch len(rec.arrs) { + case 0: + rec.rows = 0 + default: + rec.rows = int64(rec.arrs[0].Len()) + } + } + + err := rec.validate() + if err != nil { + rec.Release() + panic(err) + } + + return rec +} + +func (rec *simpleRecord) SetColumn(i int, arr arrow.Array) (arrow.Record, error) { + if i < 0 || i >= len(rec.arrs) { + return nil, fmt.Errorf("arrow/array: column index out of range [0, %d): got=%d", len(rec.arrs), i) + } + + if arr.Len() != int(rec.rows) { + return nil, fmt.Errorf("arrow/array: mismatch number of rows in column %q: got=%d, want=%d", + rec.schema.Field(i).Name, + arr.Len(), rec.rows, + ) + } + + f := rec.schema.Field(i) + if !arrow.TypeEqual(f.Type, arr.DataType()) { + return nil, fmt.Errorf("arrow/array: column %q type mismatch: got=%v, want=%v", + f.Name, + arr.DataType(), f.Type, + ) + } + arrs := make([]arrow.Array, len(rec.arrs)) + copy(arrs, rec.arrs) + arrs[i] = arr + + return NewRecord(rec.schema, arrs, rec.rows), nil +} + +func (rec *simpleRecord) validate() error { + if rec.rows == 0 && len(rec.arrs) == 0 { + return nil + } + + if len(rec.arrs) != len(rec.schema.Fields()) { + return fmt.Errorf("arrow/array: number of columns/fields mismatch") + } + + for i, arr := range rec.arrs { + f := rec.schema.Field(i) + if int64(arr.Len()) < rec.rows { + return fmt.Errorf("arrow/array: mismatch number of rows in column %q: got=%d, want=%d", + f.Name, + arr.Len(), rec.rows, + ) + } + if !arrow.TypeEqual(f.Type, arr.DataType()) { + return fmt.Errorf("arrow/array: column %q type mismatch: got=%v, want=%v", + f.Name, + arr.DataType(), f.Type, + ) + } + } + return nil +} + +// Retain increases the reference count by 1. +// Retain may be called simultaneously from multiple goroutines. +func (rec *simpleRecord) Retain() { + atomic.AddInt64(&rec.refCount, 1) +} + +// Release decreases the reference count by 1. +// When the reference count goes to zero, the memory is freed. +// Release may be called simultaneously from multiple goroutines. +func (rec *simpleRecord) Release() { + debug.Assert(atomic.LoadInt64(&rec.refCount) > 0, "too many releases") + + if atomic.AddInt64(&rec.refCount, -1) == 0 { + for _, arr := range rec.arrs { + arr.Release() + } + rec.arrs = nil + } +} + +func (rec *simpleRecord) Schema() *arrow.Schema { return rec.schema } +func (rec *simpleRecord) NumRows() int64 { return rec.rows } +func (rec *simpleRecord) NumCols() int64 { return int64(len(rec.arrs)) } +func (rec *simpleRecord) Columns() []arrow.Array { return rec.arrs } +func (rec *simpleRecord) Column(i int) arrow.Array { return rec.arrs[i] } +func (rec *simpleRecord) ColumnName(i int) string { return rec.schema.Field(i).Name } + +// NewSlice constructs a zero-copy slice of the record with the indicated +// indices i and j, corresponding to array[i:j]. +// The returned record must be Release()'d after use. +// +// NewSlice panics if the slice is outside the valid range of the record array. +// NewSlice panics if j < i. +func (rec *simpleRecord) NewSlice(i, j int64) arrow.Record { + arrs := make([]arrow.Array, len(rec.arrs)) + for ii, arr := range rec.arrs { + arrs[ii] = NewSlice(arr, i, j) + } + defer func() { + for _, arr := range arrs { + arr.Release() + } + }() + return NewRecord(rec.schema, arrs, j-i) +} + +func (rec *simpleRecord) String() string { + o := new(strings.Builder) + fmt.Fprintf(o, "record:\n %v\n", rec.schema) + fmt.Fprintf(o, " rows: %d\n", rec.rows) + for i, col := range rec.arrs { + fmt.Fprintf(o, " col[%d][%s]: %v\n", i, rec.schema.Field(i).Name, col) + } + + return o.String() +} + +func (rec *simpleRecord) MarshalJSON() ([]byte, error) { + arr := RecordToStructArray(rec) + defer arr.Release() + return arr.MarshalJSON() +} + +// RecordBuilder eases the process of building a Record, iteratively, from +// a known Schema. +type RecordBuilder struct { + refCount int64 + mem memory.Allocator + schema *arrow.Schema + fields []Builder +} + +// NewRecordBuilder returns a builder, using the provided memory allocator and a schema. +func NewRecordBuilder(mem memory.Allocator, schema *arrow.Schema) *RecordBuilder { + b := &RecordBuilder{ + refCount: 1, + mem: mem, + schema: schema, + fields: make([]Builder, len(schema.Fields())), + } + + for i, f := range schema.Fields() { + b.fields[i] = NewBuilder(b.mem, f.Type) + } + + return b +} + +// Retain increases the reference count by 1. +// Retain may be called simultaneously from multiple goroutines. +func (b *RecordBuilder) Retain() { + atomic.AddInt64(&b.refCount, 1) +} + +// Release decreases the reference count by 1. +func (b *RecordBuilder) Release() { + debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases") + + if atomic.AddInt64(&b.refCount, -1) == 0 { + for _, f := range b.fields { + f.Release() + } + b.fields = nil + } +} + +func (b *RecordBuilder) Schema() *arrow.Schema { return b.schema } +func (b *RecordBuilder) Fields() []Builder { return b.fields } +func (b *RecordBuilder) Field(i int) Builder { return b.fields[i] } + +func (b *RecordBuilder) Reserve(size int) { + for _, f := range b.fields { + f.Reserve(size) + } +} + +// NewRecord creates a new record from the memory buffers and resets the +// RecordBuilder so it can be used to build a new record. +// +// The returned Record must be Release()'d after use. +// +// NewRecord panics if the fields' builder do not have the same length. +func (b *RecordBuilder) NewRecord() arrow.Record { + cols := make([]arrow.Array, len(b.fields)) + rows := int64(0) + + defer func(cols []arrow.Array) { + for _, col := range cols { + if col == nil { + continue + } + col.Release() + } + }(cols) + + for i, f := range b.fields { + cols[i] = f.NewArray() + irow := int64(cols[i].Len()) + if i > 0 && irow != rows { + panic(fmt.Errorf("arrow/array: field %d has %d rows. want=%d", i, irow, rows)) + } + rows = irow + } + + return NewRecord(b.schema, cols, rows) +} + +// UnmarshalJSON for record builder will read in a single object and add the values +// to each field in the recordbuilder, missing fields will get a null and unexpected +// keys will be ignored. If reading in an array of records as a single batch, then use +// a structbuilder and use RecordFromStruct. +func (b *RecordBuilder) UnmarshalJSON(data []byte) error { + dec := json.NewDecoder(bytes.NewReader(data)) + // should start with a '{' + t, err := dec.Token() + if err != nil { + return err + } + + if delim, ok := t.(json.Delim); !ok || delim != '{' { + return fmt.Errorf("record should start with '{', not %s", t) + } + + keylist := make(map[string]bool) + for dec.More() { + keyTok, err := dec.Token() + if err != nil { + return err + } + + key := keyTok.(string) + if keylist[key] { + return fmt.Errorf("key %s shows up twice in row to be decoded", key) + } + keylist[key] = true + + indices := b.schema.FieldIndices(key) + if len(indices) == 0 { + var extra interface{} + if err := dec.Decode(&extra); err != nil { + return err + } + continue + } + + if err := b.fields[indices[0]].UnmarshalOne(dec); err != nil { + return err + } + } + + for i, f := range b.schema.Fields() { + if !keylist[f.Name] { + b.fields[i].AppendNull() + } + } + return nil +} + +var ( + _ arrow.Record = (*simpleRecord)(nil) + _ RecordReader = (*simpleRecords)(nil) +) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array/string.go b/vendor/github.com/apache/arrow/go/v14/arrow/array/string.go new file mode 100644 index 000000000..86e27c970 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array/string.go @@ -0,0 +1,521 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package array + +import ( + "bytes" + "fmt" + "reflect" + "strings" + "unsafe" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/memory" + "github.com/apache/arrow/go/v14/internal/json" +) + +// String represents an immutable sequence of variable-length UTF-8 strings. +type String struct { + array + offsets []int32 + values string +} + +// NewStringData constructs a new String array from data. +func NewStringData(data arrow.ArrayData) *String { + a := &String{} + a.refCount = 1 + a.setData(data.(*Data)) + return a +} + +// Reset resets the String with a different set of Data. +func (a *String) Reset(data arrow.ArrayData) { + a.setData(data.(*Data)) +} + +// Value returns the slice at index i. This value should not be mutated. +func (a *String) Value(i int) string { + i = i + a.array.data.offset + return a.values[a.offsets[i]:a.offsets[i+1]] +} + +func (a *String) ValueStr(i int) string { + if a.IsNull(i) { + return NullValueStr + } + return a.Value(i) +} + +// ValueOffset returns the offset of the value at index i. +func (a *String) ValueOffset(i int) int { + if i < 0 || i > a.array.data.length { + panic("arrow/array: index out of range") + } + return int(a.offsets[i+a.array.data.offset]) +} + +func (a *String) ValueOffset64(i int) int64 { + return int64(a.ValueOffset(i)) +} + +func (a *String) ValueLen(i int) int { + if i < 0 || i >= a.array.data.length { + panic("arrow/array: index out of range") + } + beg := a.array.data.offset + i + return int(a.offsets[beg+1] - a.offsets[beg]) +} + +func (a *String) ValueOffsets() []int32 { + beg := a.array.data.offset + end := beg + a.array.data.length + 1 + return a.offsets[beg:end] +} + +func (a *String) ValueBytes() []byte { + beg := a.array.data.offset + end := beg + a.array.data.length + if a.array.data.buffers[2] != nil { + return a.array.data.buffers[2].Bytes()[a.offsets[beg]:a.offsets[end]] + } + return nil +} + +func (a *String) String() string { + o := new(strings.Builder) + o.WriteString("[") + for i := 0; i < a.Len(); i++ { + if i > 0 { + o.WriteString(" ") + } + switch { + case a.IsNull(i): + o.WriteString(NullValueStr) + default: + fmt.Fprintf(o, "%q", a.Value(i)) + } + } + o.WriteString("]") + return o.String() +} + +func (a *String) setData(data *Data) { + if len(data.buffers) != 3 { + panic("arrow/array: len(data.buffers) != 3") + } + + a.array.setData(data) + + if vdata := data.buffers[2]; vdata != nil { + b := vdata.Bytes() + a.values = *(*string)(unsafe.Pointer(&b)) + } + + if offsets := data.buffers[1]; offsets != nil { + a.offsets = arrow.Int32Traits.CastFromBytes(offsets.Bytes()) + } + + if a.array.data.length < 1 { + return + } + + expNumOffsets := a.array.data.offset + a.array.data.length + 1 + if len(a.offsets) < expNumOffsets { + panic(fmt.Errorf("arrow/array: string offset buffer must have at least %d values", expNumOffsets)) + } + + if int(a.offsets[expNumOffsets-1]) > len(a.values) { + panic("arrow/array: string offsets out of bounds of data buffer") + } +} + +func (a *String) GetOneForMarshal(i int) interface{} { + if a.IsValid(i) { + return a.Value(i) + } + return nil +} + +func (a *String) MarshalJSON() ([]byte, error) { + vals := make([]interface{}, a.Len()) + for i := 0; i < a.Len(); i++ { + if a.IsValid(i) { + vals[i] = a.Value(i) + } else { + vals[i] = nil + } + } + return json.Marshal(vals) +} + +func arrayEqualString(left, right *String) bool { + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + if left.Value(i) != right.Value(i) { + return false + } + } + return true +} + +// String represents an immutable sequence of variable-length UTF-8 strings. +type LargeString struct { + array + offsets []int64 + values string +} + +// NewStringData constructs a new String array from data. +func NewLargeStringData(data arrow.ArrayData) *LargeString { + a := &LargeString{} + a.refCount = 1 + a.setData(data.(*Data)) + return a +} + +// Reset resets the String with a different set of Data. +func (a *LargeString) Reset(data arrow.ArrayData) { + a.setData(data.(*Data)) +} + +// Value returns the slice at index i. This value should not be mutated. +func (a *LargeString) Value(i int) string { + i = i + a.array.data.offset + return a.values[a.offsets[i]:a.offsets[i+1]] +} + +func (a *LargeString) ValueStr(i int) string { + if a.IsNull(i) { + return NullValueStr + } + return a.Value(i) +} + +// ValueOffset returns the offset of the value at index i. +func (a *LargeString) ValueOffset(i int) int64 { + if i < 0 || i > a.array.data.length { + panic("arrow/array: index out of range") + } + return a.offsets[i+a.array.data.offset] +} + +func (a *LargeString) ValueOffset64(i int) int64 { + return a.ValueOffset(i) +} + +func (a *LargeString) ValueOffsets() []int64 { + beg := a.array.data.offset + end := beg + a.array.data.length + 1 + return a.offsets[beg:end] +} + +func (a *LargeString) ValueBytes() []byte { + beg := a.array.data.offset + end := beg + a.array.data.length + if a.array.data.buffers[2] != nil { + return a.array.data.buffers[2].Bytes()[a.offsets[beg]:a.offsets[end]] + } + return nil +} + +func (a *LargeString) String() string { + o := new(strings.Builder) + o.WriteString("[") + for i := 0; i < a.Len(); i++ { + if i > 0 { + o.WriteString(" ") + } + switch { + case a.IsNull(i): + o.WriteString(NullValueStr) + default: + fmt.Fprintf(o, "%q", a.Value(i)) + } + } + o.WriteString("]") + return o.String() +} + +func (a *LargeString) setData(data *Data) { + if len(data.buffers) != 3 { + panic("arrow/array: len(data.buffers) != 3") + } + + a.array.setData(data) + + if vdata := data.buffers[2]; vdata != nil { + b := vdata.Bytes() + a.values = *(*string)(unsafe.Pointer(&b)) + } + + if offsets := data.buffers[1]; offsets != nil { + a.offsets = arrow.Int64Traits.CastFromBytes(offsets.Bytes()) + } + + if a.array.data.length < 1 { + return + } + + expNumOffsets := a.array.data.offset + a.array.data.length + 1 + if len(a.offsets) < expNumOffsets { + panic(fmt.Errorf("arrow/array: string offset buffer must have at least %d values", expNumOffsets)) + } + + if int(a.offsets[expNumOffsets-1]) > len(a.values) { + panic("arrow/array: string offsets out of bounds of data buffer") + } +} + +func (a *LargeString) GetOneForMarshal(i int) interface{} { + if a.IsValid(i) { + return a.Value(i) + } + return nil +} + +func (a *LargeString) MarshalJSON() ([]byte, error) { + vals := make([]interface{}, a.Len()) + for i := 0; i < a.Len(); i++ { + vals[i] = a.GetOneForMarshal(i) + } + return json.Marshal(vals) +} + +func arrayEqualLargeString(left, right *LargeString) bool { + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + if left.Value(i) != right.Value(i) { + return false + } + } + return true +} + +// A StringBuilder is used to build a String array using the Append methods. +type StringBuilder struct { + *BinaryBuilder +} + +// NewStringBuilder creates a new StringBuilder. +func NewStringBuilder(mem memory.Allocator) *StringBuilder { + b := &StringBuilder{ + BinaryBuilder: NewBinaryBuilder(mem, arrow.BinaryTypes.String), + } + return b +} + +func (b *StringBuilder) Type() arrow.DataType { + return arrow.BinaryTypes.String +} + +// Append appends a string to the builder. +func (b *StringBuilder) Append(v string) { + b.BinaryBuilder.Append([]byte(v)) +} + +// AppendValues will append the values in the v slice. The valid slice determines which values +// in v are valid (not null). The valid slice must either be empty or be equal in length to v. If empty, +// all values in v are appended and considered valid. +func (b *StringBuilder) AppendValues(v []string, valid []bool) { + b.BinaryBuilder.AppendStringValues(v, valid) +} + +// Value returns the string at index i. +func (b *StringBuilder) Value(i int) string { + return string(b.BinaryBuilder.Value(i)) +} + +// func (b *StringBuilder) UnsafeAppend(v string) { +// b.BinaryBuilder.UnsafeAppend([]byte(v)) +// } + +// NewArray creates a String array from the memory buffers used by the builder and resets the StringBuilder +// so it can be used to build a new array. +func (b *StringBuilder) NewArray() arrow.Array { + return b.NewStringArray() +} + +// NewStringArray creates a String array from the memory buffers used by the builder and resets the StringBuilder +// so it can be used to build a new array. +func (b *StringBuilder) NewStringArray() (a *String) { + data := b.newData() + a = NewStringData(data) + data.Release() + return +} + +func (b *StringBuilder) UnmarshalOne(dec *json.Decoder) error { + t, err := dec.Token() + if err != nil { + return err + } + + switch v := t.(type) { + case nil: + b.AppendNull() + case string: + b.Append(v) + default: + return &json.UnmarshalTypeError{ + Value: fmt.Sprint(v), + Type: reflect.TypeOf(string("")), + Offset: dec.InputOffset(), + } + } + return nil +} + +func (b *StringBuilder) Unmarshal(dec *json.Decoder) error { + for dec.More() { + if err := b.UnmarshalOne(dec); err != nil { + return err + } + } + return nil +} + +func (b *StringBuilder) UnmarshalJSON(data []byte) error { + dec := json.NewDecoder(bytes.NewReader(data)) + t, err := dec.Token() + if err != nil { + return err + } + + if delim, ok := t.(json.Delim); !ok || delim != '[' { + return fmt.Errorf("string builder must unpack from json array, found %s", delim) + } + + return b.Unmarshal(dec) +} + +// A LargeStringBuilder is used to build a LargeString array using the Append methods. +// LargeString is for when you need the offset buffer to be 64-bit integers +// instead of 32-bit integers. +type LargeStringBuilder struct { + *BinaryBuilder +} + +// NewStringBuilder creates a new StringBuilder. +func NewLargeStringBuilder(mem memory.Allocator) *LargeStringBuilder { + b := &LargeStringBuilder{ + BinaryBuilder: NewBinaryBuilder(mem, arrow.BinaryTypes.LargeString), + } + return b +} + +func (b *LargeStringBuilder) Type() arrow.DataType { return arrow.BinaryTypes.LargeString } + +// Append appends a string to the builder. +func (b *LargeStringBuilder) Append(v string) { + b.BinaryBuilder.Append([]byte(v)) +} + +// AppendValues will append the values in the v slice. The valid slice determines which values +// in v are valid (not null). The valid slice must either be empty or be equal in length to v. If empty, +// all values in v are appended and considered valid. +func (b *LargeStringBuilder) AppendValues(v []string, valid []bool) { + b.BinaryBuilder.AppendStringValues(v, valid) +} + +// Value returns the string at index i. +func (b *LargeStringBuilder) Value(i int) string { + return string(b.BinaryBuilder.Value(i)) +} + +// func (b *LargeStringBuilder) UnsafeAppend(v string) { +// b.BinaryBuilder.UnsafeAppend([]byte(v)) +// } + +// NewArray creates a String array from the memory buffers used by the builder and resets the StringBuilder +// so it can be used to build a new array. +func (b *LargeStringBuilder) NewArray() arrow.Array { + return b.NewLargeStringArray() +} + +// NewStringArray creates a String array from the memory buffers used by the builder and resets the StringBuilder +// so it can be used to build a new array. +func (b *LargeStringBuilder) NewLargeStringArray() (a *LargeString) { + data := b.newData() + a = NewLargeStringData(data) + data.Release() + return +} + +func (b *LargeStringBuilder) UnmarshalOne(dec *json.Decoder) error { + t, err := dec.Token() + if err != nil { + return err + } + + switch v := t.(type) { + case nil: + b.AppendNull() + case string: + b.Append(v) + default: + return &json.UnmarshalTypeError{ + Value: fmt.Sprint(v), + Type: reflect.TypeOf(string("")), + Offset: dec.InputOffset(), + } + } + return nil +} + +func (b *LargeStringBuilder) Unmarshal(dec *json.Decoder) error { + for dec.More() { + if err := b.UnmarshalOne(dec); err != nil { + return err + } + } + return nil +} + +func (b *LargeStringBuilder) UnmarshalJSON(data []byte) error { + dec := json.NewDecoder(bytes.NewReader(data)) + t, err := dec.Token() + if err != nil { + return err + } + + if delim, ok := t.(json.Delim); !ok || delim != '[' { + return fmt.Errorf("string builder must unpack from json array, found %s", delim) + } + + return b.Unmarshal(dec) +} + +type StringLikeBuilder interface { + Builder + Append(string) + UnsafeAppend([]byte) + ReserveData(int) +} + +var ( + _ arrow.Array = (*String)(nil) + _ arrow.Array = (*LargeString)(nil) + _ Builder = (*StringBuilder)(nil) + _ Builder = (*LargeStringBuilder)(nil) + _ StringLikeBuilder = (*StringBuilder)(nil) + _ StringLikeBuilder = (*LargeStringBuilder)(nil) +) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array/struct.go b/vendor/github.com/apache/arrow/go/v14/arrow/array/struct.go new file mode 100644 index 000000000..248a25bf6 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array/struct.go @@ -0,0 +1,491 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package array + +import ( + "bytes" + "errors" + "fmt" + "strings" + "sync/atomic" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/bitutil" + "github.com/apache/arrow/go/v14/arrow/internal/debug" + "github.com/apache/arrow/go/v14/arrow/memory" + "github.com/apache/arrow/go/v14/internal/json" +) + +// Struct represents an ordered sequence of relative types. +type Struct struct { + array + fields []arrow.Array +} + +// NewStructArray constructs a new Struct Array out of the columns passed +// in and the field names. The length of all cols must be the same and +// there should be the same number of columns as names. +func NewStructArray(cols []arrow.Array, names []string) (*Struct, error) { + return NewStructArrayWithNulls(cols, names, nil, 0, 0) +} + +// NewStructArrayWithNulls is like NewStructArray as a convenience function, +// but also takes in a null bitmap, the number of nulls, and an optional offset +// to use for creating the Struct Array. +func NewStructArrayWithNulls(cols []arrow.Array, names []string, nullBitmap *memory.Buffer, nullCount int, offset int) (*Struct, error) { + if len(cols) != len(names) { + return nil, fmt.Errorf("%w: mismatching number of fields and child arrays", arrow.ErrInvalid) + } + if len(cols) == 0 { + return nil, fmt.Errorf("%w: can't infer struct array length with 0 child arrays", arrow.ErrInvalid) + } + length := cols[0].Len() + children := make([]arrow.ArrayData, len(cols)) + fields := make([]arrow.Field, len(cols)) + for i, c := range cols { + if length != c.Len() { + return nil, fmt.Errorf("%w: mismatching child array lengths", arrow.ErrInvalid) + } + children[i] = c.Data() + fields[i].Name = names[i] + fields[i].Type = c.DataType() + fields[i].Nullable = true + } + data := NewData(arrow.StructOf(fields...), length, []*memory.Buffer{nullBitmap}, children, nullCount, offset) + defer data.Release() + return NewStructData(data), nil +} + +// NewStructData returns a new Struct array value from data. +func NewStructData(data arrow.ArrayData) *Struct { + a := &Struct{} + a.refCount = 1 + a.setData(data.(*Data)) + return a +} + +func (a *Struct) NumField() int { return len(a.fields) } +func (a *Struct) Field(i int) arrow.Array { return a.fields[i] } + +// ValueStr returns the string representation (as json) of the value at index i. +func (a *Struct) ValueStr(i int) string { + if a.IsNull(i) { + return NullValueStr + } + + data, err := json.Marshal(a.GetOneForMarshal(i)) + if err != nil { + panic(err) + } + return string(data) +} + +func (a *Struct) String() string { + o := new(strings.Builder) + o.WriteString("{") + + structBitmap := a.NullBitmapBytes() + for i, v := range a.fields { + if i > 0 { + o.WriteString(" ") + } + if arrow.IsUnion(v.DataType().ID()) { + fmt.Fprintf(o, "%v", v) + continue + } else if !bytes.Equal(structBitmap, v.NullBitmapBytes()) { + masked := a.newStructFieldWithParentValidityMask(i) + fmt.Fprintf(o, "%v", masked) + masked.Release() + continue + } + fmt.Fprintf(o, "%v", v) + } + o.WriteString("}") + return o.String() +} + +// newStructFieldWithParentValidityMask returns the Interface at fieldIndex +// with a nullBitmapBytes adjusted according on the parent struct nullBitmapBytes. +// From the docs: +// +// "When reading the struct array the parent validity bitmap takes priority." +func (a *Struct) newStructFieldWithParentValidityMask(fieldIndex int) arrow.Array { + field := a.Field(fieldIndex) + nullBitmapBytes := field.NullBitmapBytes() + maskedNullBitmapBytes := make([]byte, len(nullBitmapBytes)) + copy(maskedNullBitmapBytes, nullBitmapBytes) + for i := 0; i < field.Len(); i++ { + if a.IsNull(i) { + bitutil.ClearBit(maskedNullBitmapBytes, i) + } + } + data := NewSliceData(field.Data(), 0, int64(field.Len())).(*Data) + defer data.Release() + bufs := make([]*memory.Buffer, len(data.Buffers())) + copy(bufs, data.buffers) + bufs[0].Release() + bufs[0] = memory.NewBufferBytes(maskedNullBitmapBytes) + data.buffers = bufs + maskedField := MakeFromData(data) + return maskedField +} + +func (a *Struct) setData(data *Data) { + a.array.setData(data) + a.fields = make([]arrow.Array, len(data.childData)) + for i, child := range data.childData { + if data.offset != 0 || child.Len() != data.length { + sub := NewSliceData(child, int64(data.offset), int64(data.offset+data.length)) + a.fields[i] = MakeFromData(sub) + sub.Release() + } else { + a.fields[i] = MakeFromData(child) + } + } +} + +func (a *Struct) GetOneForMarshal(i int) interface{} { + if a.IsNull(i) { + return nil + } + + tmp := make(map[string]interface{}) + fieldList := a.data.dtype.(*arrow.StructType).Fields() + for j, d := range a.fields { + tmp[fieldList[j].Name] = d.GetOneForMarshal(i) + } + return tmp +} + +func (a *Struct) MarshalJSON() ([]byte, error) { + var buf bytes.Buffer + enc := json.NewEncoder(&buf) + + buf.WriteByte('[') + for i := 0; i < a.Len(); i++ { + if i != 0 { + buf.WriteByte(',') + } + if err := enc.Encode(a.GetOneForMarshal(i)); err != nil { + return nil, err + } + } + buf.WriteByte(']') + return buf.Bytes(), nil +} + +func arrayEqualStruct(left, right *Struct) bool { + for i, lf := range left.fields { + rf := right.fields[i] + if !Equal(lf, rf) { + return false + } + } + return true +} + +func (a *Struct) Retain() { + a.array.Retain() + for _, f := range a.fields { + f.Retain() + } +} + +func (a *Struct) Release() { + a.array.Release() + for _, f := range a.fields { + f.Release() + } +} + +type StructBuilder struct { + builder + + dtype arrow.DataType + fields []Builder +} + +// NewStructBuilder returns a builder, using the provided memory allocator. +func NewStructBuilder(mem memory.Allocator, dtype *arrow.StructType) *StructBuilder { + b := &StructBuilder{ + builder: builder{refCount: 1, mem: mem}, + dtype: dtype, + fields: make([]Builder, len(dtype.Fields())), + } + for i, f := range dtype.Fields() { + b.fields[i] = NewBuilder(b.mem, f.Type) + } + return b +} + +func (b *StructBuilder) Type() arrow.DataType { + fields := make([]arrow.Field, len(b.fields)) + copy(fields, b.dtype.(*arrow.StructType).Fields()) + for i, b := range b.fields { + fields[i].Type = b.Type() + } + return arrow.StructOf(fields...) +} + +// Release decreases the reference count by 1. +// When the reference count goes to zero, the memory is freed. +func (b *StructBuilder) Release() { + debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases") + + if atomic.AddInt64(&b.refCount, -1) == 0 { + if b.nullBitmap != nil { + b.nullBitmap.Release() + b.nullBitmap = nil + } + + for _, f := range b.fields { + f.Release() + } + } +} + +func (b *StructBuilder) Append(v bool) { + // Intentionally not calling `Reserve` as it will recursively call + // `Reserve` on the child builders, which during profiling has shown to be + // very expensive due to iterating over children, dynamic dispatch and all + // other code that gets executed even if previously `Reserve` was called to + // preallocate. Not calling `Reserve` has no downsides as when appending to + // the underlying children they already ensure they have enough space + // reserved. The only thing we must do is ensure we have enough space in + // the validity bitmap of the struct builder itself. + b.builder.reserve(1, b.resizeHelper) + b.unsafeAppendBoolToBitmap(v) + if !v { + for _, f := range b.fields { + f.AppendNull() + } + } +} + +func (b *StructBuilder) AppendValues(valids []bool) { + b.Reserve(len(valids)) + b.builder.unsafeAppendBoolsToBitmap(valids, len(valids)) +} + +func (b *StructBuilder) AppendNull() { b.Append(false) } + +func (b *StructBuilder) AppendNulls(n int) { + for i := 0; i < n; i++ { + b.AppendNull() + } +} + +func (b *StructBuilder) AppendEmptyValue() { + b.Append(true) + for _, f := range b.fields { + f.AppendEmptyValue() + } +} + +func (b *StructBuilder) AppendEmptyValues(n int) { + for i := 0; i < n; i++ { + b.AppendEmptyValue() + } +} + +func (b *StructBuilder) unsafeAppendBoolToBitmap(isValid bool) { + if isValid { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + } else { + b.nulls++ + } + b.length++ +} + +func (b *StructBuilder) init(capacity int) { + b.builder.init(capacity) +} + +// Reserve ensures there is enough space for appending n elements +// by checking the capacity and calling Resize if necessary. +func (b *StructBuilder) Reserve(n int) { + b.builder.reserve(n, b.resizeHelper) + for _, f := range b.fields { + f.Reserve(n) + } +} + +// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(), +// additional memory will be allocated. If n is smaller, the allocated memory may reduced. +func (b *StructBuilder) Resize(n int) { + b.resizeHelper(n) + for _, f := range b.fields { + f.Resize(n) + } +} + +func (b *StructBuilder) resizeHelper(n int) { + if n < minBuilderCapacity { + n = minBuilderCapacity + } + + if b.capacity == 0 { + b.init(n) + } else { + b.builder.resize(n, b.builder.init) + } +} + +func (b *StructBuilder) NumField() int { return len(b.fields) } +func (b *StructBuilder) FieldBuilder(i int) Builder { return b.fields[i] } + +// NewArray creates a Struct array from the memory buffers used by the builder and resets the StructBuilder +// so it can be used to build a new array. +func (b *StructBuilder) NewArray() arrow.Array { + return b.NewStructArray() +} + +// NewStructArray creates a Struct array from the memory buffers used by the builder and resets the StructBuilder +// so it can be used to build a new array. +func (b *StructBuilder) NewStructArray() (a *Struct) { + data := b.newData() + a = NewStructData(data) + data.Release() + return +} + +func (b *StructBuilder) newData() (data *Data) { + fields := make([]arrow.ArrayData, len(b.fields)) + for i, f := range b.fields { + arr := f.NewArray() + defer arr.Release() + fields[i] = arr.Data() + } + + data = NewData( + b.Type(), b.length, + []*memory.Buffer{ + b.nullBitmap, + }, + fields, + b.nulls, + 0, + ) + b.reset() + + return +} + +func (b *StructBuilder) AppendValueFromString(s string) error { + if s == NullValueStr { + b.AppendNull() + return nil + } + + if !strings.HasPrefix(s, "{") && !strings.HasSuffix(s, "}") { + return fmt.Errorf("%w: invalid string for struct should be be of form: {*}", arrow.ErrInvalid) + } + dec := json.NewDecoder(strings.NewReader(s)) + return b.UnmarshalOne(dec) +} + +func (b *StructBuilder) UnmarshalOne(dec *json.Decoder) error { + t, err := dec.Token() + if err != nil { + return err + } + + switch t { + case json.Delim('{'): + b.Append(true) + keylist := make(map[string]bool) + for dec.More() { + keyTok, err := dec.Token() + if err != nil { + return err + } + + key, ok := keyTok.(string) + if !ok { + return errors.New("missing key") + } + + if keylist[key] { + return fmt.Errorf("key %s is specified twice", key) + } + + keylist[key] = true + + idx, ok := b.dtype.(*arrow.StructType).FieldIdx(key) + if !ok { + var extra interface{} + dec.Decode(&extra) + continue + } + + if err := b.fields[idx].UnmarshalOne(dec); err != nil { + return err + } + } + + // Append null values to all optional fields that were not presented in the json input + for _, field := range b.dtype.(*arrow.StructType).Fields() { + if !field.Nullable { + continue + } + idx, _ := b.dtype.(*arrow.StructType).FieldIdx(field.Name) + if _, hasKey := keylist[field.Name]; !hasKey { + b.fields[idx].AppendNull() + } + } + + // consume '}' + _, err := dec.Token() + return err + case nil: + b.AppendNull() + default: + return &json.UnmarshalTypeError{ + Offset: dec.InputOffset(), + Struct: fmt.Sprint(b.dtype), + } + } + return nil +} + +func (b *StructBuilder) Unmarshal(dec *json.Decoder) error { + for dec.More() { + if err := b.UnmarshalOne(dec); err != nil { + return err + } + } + return nil +} + +func (b *StructBuilder) UnmarshalJSON(data []byte) error { + dec := json.NewDecoder(bytes.NewReader(data)) + t, err := dec.Token() + if err != nil { + return err + } + + if delim, ok := t.(json.Delim); !ok || delim != '[' { + return fmt.Errorf("struct builder must unpack from json array, found %s", delim) + } + + return b.Unmarshal(dec) +} + +var ( + _ arrow.Array = (*Struct)(nil) + _ Builder = (*StructBuilder)(nil) +) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array/table.go b/vendor/github.com/apache/arrow/go/v14/arrow/array/table.go new file mode 100644 index 000000000..6456992e3 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array/table.go @@ -0,0 +1,421 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package array + +import ( + "errors" + "fmt" + "math" + "strings" + "sync/atomic" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/internal/debug" +) + +// NewColumnSlice returns a new zero-copy slice of the column with the indicated +// indices i and j, corresponding to the column's array[i:j]. +// The returned column must be Release()'d after use. +// +// NewColSlice panics if the slice is outside the valid range of the column's array. +// NewColSlice panics if j < i. +func NewColumnSlice(col *arrow.Column, i, j int64) *arrow.Column { + slice := NewChunkedSlice(col.Data(), i, j) + defer slice.Release() + return arrow.NewColumn(col.Field(), slice) +} + +// NewChunkedSlice constructs a zero-copy slice of the chunked array with the indicated +// indices i and j, corresponding to array[i:j]. +// The returned chunked array must be Release()'d after use. +// +// NewSlice panics if the slice is outside the valid range of the input array. +// NewSlice panics if j < i. +func NewChunkedSlice(a *arrow.Chunked, i, j int64) *arrow.Chunked { + if j > int64(a.Len()) || i > j || i > int64(a.Len()) { + panic("arrow/array: index out of range") + } + + var ( + cur = 0 + beg = i + sz = j - i + chunks = make([]arrow.Array, 0, len(a.Chunks())) + ) + + for cur < len(a.Chunks()) && beg >= int64(a.Chunks()[cur].Len()) { + beg -= int64(a.Chunks()[cur].Len()) + cur++ + } + + for cur < len(a.Chunks()) && sz > 0 { + arr := a.Chunks()[cur] + end := beg + sz + if end > int64(arr.Len()) { + end = int64(arr.Len()) + } + chunks = append(chunks, NewSlice(arr, beg, end)) + sz -= int64(arr.Len()) - beg + beg = 0 + cur++ + } + chunks = chunks[:len(chunks):len(chunks)] + defer func() { + for _, chunk := range chunks { + chunk.Release() + } + }() + + return arrow.NewChunked(a.DataType(), chunks) +} + +// simpleTable is a basic, non-lazy in-memory table. +type simpleTable struct { + refCount int64 + + rows int64 + cols []arrow.Column + + schema *arrow.Schema +} + +// NewTable returns a new basic, non-lazy in-memory table. +// If rows is negative, the number of rows will be inferred from the height +// of the columns. +// +// NewTable panics if the columns and schema are inconsistent. +// NewTable panics if rows is larger than the height of the columns. +func NewTable(schema *arrow.Schema, cols []arrow.Column, rows int64) *simpleTable { + tbl := simpleTable{ + refCount: 1, + rows: rows, + cols: cols, + schema: schema, + } + + if tbl.rows < 0 { + switch len(tbl.cols) { + case 0: + tbl.rows = 0 + default: + tbl.rows = int64(tbl.cols[0].Len()) + } + } + + // validate the table and its constituents. + // note we retain the columns after having validated the table + // in case the validation fails and panics (and would otherwise leak + // a ref-count on the columns.) + tbl.validate() + + for i := range tbl.cols { + tbl.cols[i].Retain() + } + + return &tbl +} + +// NewTableFromSlice is a convenience function to create a table from a slice +// of slices of arrow.Array. +// +// Like other NewTable functions this can panic if: +// - len(schema.Fields) != len(data) +// - the total length of each column's array slice (ie: number of rows +// in the column) aren't the same for all columns. +func NewTableFromSlice(schema *arrow.Schema, data [][]arrow.Array) *simpleTable { + if len(data) != len(schema.Fields()) { + panic("array/table: mismatch in number of columns and data for creating a table") + } + + cols := make([]arrow.Column, len(schema.Fields())) + for i, arrs := range data { + field := schema.Field(i) + chunked := arrow.NewChunked(field.Type, arrs) + cols[i] = *arrow.NewColumn(field, chunked) + chunked.Release() + } + + tbl := simpleTable{ + refCount: 1, + schema: schema, + cols: cols, + rows: int64(cols[0].Len()), + } + + defer func() { + if r := recover(); r != nil { + // if validate panics, let's release the columns + // so that we don't leak them, then propagate the panic + for _, c := range cols { + c.Release() + } + panic(r) + } + }() + // validate the table and its constituents. + tbl.validate() + + return &tbl +} + +// NewTableFromRecords returns a new basic, non-lazy in-memory table. +// +// NewTableFromRecords panics if the records and schema are inconsistent. +func NewTableFromRecords(schema *arrow.Schema, recs []arrow.Record) *simpleTable { + arrs := make([]arrow.Array, len(recs)) + cols := make([]arrow.Column, len(schema.Fields())) + + defer func(cols []arrow.Column) { + for i := range cols { + cols[i].Release() + } + }(cols) + + for i := range cols { + field := schema.Field(i) + for j, rec := range recs { + arrs[j] = rec.Column(i) + } + chunk := arrow.NewChunked(field.Type, arrs) + cols[i] = *arrow.NewColumn(field, chunk) + chunk.Release() + } + + return NewTable(schema, cols, -1) +} + +func (tbl *simpleTable) Schema() *arrow.Schema { return tbl.schema } + +func (tbl *simpleTable) AddColumn(i int, field arrow.Field, column arrow.Column) (arrow.Table, error) { + if int64(column.Len()) != tbl.rows { + return nil, fmt.Errorf("arrow/array: column length mismatch: %d != %d", column.Len(), tbl.rows) + } + if field.Type != column.DataType() { + return nil, fmt.Errorf("arrow/array: column type mismatch: %v != %v", field.Type, column.DataType()) + } + newSchema, err := tbl.schema.AddField(i, field) + if err != nil { + return nil, err + } + cols := make([]arrow.Column, len(tbl.cols)+1) + copy(cols[:i], tbl.cols[:i]) + cols[i] = column + copy(cols[i+1:], tbl.cols[i:]) + newTable := NewTable(newSchema, cols, tbl.rows) + return newTable, nil +} + +func (tbl *simpleTable) NumRows() int64 { return tbl.rows } +func (tbl *simpleTable) NumCols() int64 { return int64(len(tbl.cols)) } +func (tbl *simpleTable) Column(i int) *arrow.Column { return &tbl.cols[i] } + +func (tbl *simpleTable) validate() { + if len(tbl.cols) != len(tbl.schema.Fields()) { + panic(errors.New("arrow/array: table schema mismatch")) + } + for i, col := range tbl.cols { + if !col.Field().Equal(tbl.schema.Field(i)) { + panic(fmt.Errorf("arrow/array: column field %q is inconsistent with schema", col.Name())) + } + + if int64(col.Len()) < tbl.rows { + panic(fmt.Errorf("arrow/array: column %q expected length >= %d but got length %d", col.Name(), tbl.rows, col.Len())) + } + } +} + +// Retain increases the reference count by 1. +// Retain may be called simultaneously from multiple goroutines. +func (tbl *simpleTable) Retain() { + atomic.AddInt64(&tbl.refCount, 1) +} + +// Release decreases the reference count by 1. +// When the reference count goes to zero, the memory is freed. +// Release may be called simultaneously from multiple goroutines. +func (tbl *simpleTable) Release() { + debug.Assert(atomic.LoadInt64(&tbl.refCount) > 0, "too many releases") + + if atomic.AddInt64(&tbl.refCount, -1) == 0 { + for i := range tbl.cols { + tbl.cols[i].Release() + } + tbl.cols = nil + } +} + +func (tbl *simpleTable) String() string { + o := new(strings.Builder) + o.WriteString(tbl.Schema().String()) + o.WriteString("\n") + + for i := 0; i < int(tbl.NumCols()); i++ { + col := tbl.Column(i) + o.WriteString(col.Field().Name + ": [") + for j, chunk := range col.Data().Chunks() { + if j != 0 { + o.WriteString(", ") + } + o.WriteString(chunk.String()) + } + o.WriteString("]\n") + } + return o.String() +} + +// TableReader is a Record iterator over a (possibly chunked) Table +type TableReader struct { + refCount int64 + + tbl arrow.Table + cur int64 // current row + max int64 // total number of rows + rec arrow.Record // current Record + chksz int64 // chunk size + + chunks []*arrow.Chunked + slots []int // chunk indices + offsets []int64 // chunk offsets +} + +// NewTableReader returns a new TableReader to iterate over the (possibly chunked) Table. +// if chunkSize is <= 0, the biggest possible chunk will be selected. +func NewTableReader(tbl arrow.Table, chunkSize int64) *TableReader { + ncols := tbl.NumCols() + tr := &TableReader{ + refCount: 1, + tbl: tbl, + cur: 0, + max: int64(tbl.NumRows()), + chksz: chunkSize, + chunks: make([]*arrow.Chunked, ncols), + slots: make([]int, ncols), + offsets: make([]int64, ncols), + } + tr.tbl.Retain() + + if tr.chksz <= 0 { + tr.chksz = math.MaxInt64 + } + + for i := range tr.chunks { + col := tr.tbl.Column(i) + tr.chunks[i] = col.Data() + tr.chunks[i].Retain() + } + return tr +} + +func (tr *TableReader) Schema() *arrow.Schema { return tr.tbl.Schema() } +func (tr *TableReader) Record() arrow.Record { return tr.rec } + +func (tr *TableReader) Next() bool { + if tr.cur >= tr.max { + return false + } + + if tr.rec != nil { + tr.rec.Release() + } + + // determine the minimum contiguous slice across all columns + chunksz := imin64(tr.max, tr.chksz) + chunks := make([]arrow.Array, len(tr.chunks)) + for i := range chunks { + j := tr.slots[i] + chunk := tr.chunks[i].Chunk(j) + remain := int64(chunk.Len()) - tr.offsets[i] + if remain < chunksz { + chunksz = remain + } + + chunks[i] = chunk + } + + // slice the chunks, advance each chunk slot as appropriate. + batch := make([]arrow.Array, len(tr.chunks)) + for i, chunk := range chunks { + var slice arrow.Array + offset := tr.offsets[i] + switch int64(chunk.Len()) - offset { + case chunksz: + tr.slots[i]++ + tr.offsets[i] = 0 + if offset > 0 { + // need to slice + slice = NewSlice(chunk, offset, offset+chunksz) + } else { + // no need to slice + slice = chunk + slice.Retain() + } + default: + tr.offsets[i] += chunksz + slice = NewSlice(chunk, offset, offset+chunksz) + } + batch[i] = slice + } + + tr.cur += chunksz + tr.rec = NewRecord(tr.tbl.Schema(), batch, chunksz) + + for _, arr := range batch { + arr.Release() + } + + return true +} + +// Retain increases the reference count by 1. +// Retain may be called simultaneously from multiple goroutines. +func (tr *TableReader) Retain() { + atomic.AddInt64(&tr.refCount, 1) +} + +// Release decreases the reference count by 1. +// When the reference count goes to zero, the memory is freed. +// Release may be called simultaneously from multiple goroutines. +func (tr *TableReader) Release() { + debug.Assert(atomic.LoadInt64(&tr.refCount) > 0, "too many releases") + + if atomic.AddInt64(&tr.refCount, -1) == 0 { + tr.tbl.Release() + for _, chk := range tr.chunks { + chk.Release() + } + if tr.rec != nil { + tr.rec.Release() + } + tr.tbl = nil + tr.chunks = nil + tr.slots = nil + tr.offsets = nil + } +} +func (tr *TableReader) Err() error { return nil } + +func imin64(a, b int64) int64 { + if a < b { + return a + } + return b +} + +var ( + _ arrow.Table = (*simpleTable)(nil) + _ RecordReader = (*TableReader)(nil) +) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array/timestamp.go b/vendor/github.com/apache/arrow/go/v14/arrow/array/timestamp.go new file mode 100644 index 000000000..2928b1fc7 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array/timestamp.go @@ -0,0 +1,381 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package array + +import ( + "bytes" + "fmt" + "reflect" + "strings" + "sync/atomic" + "time" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/bitutil" + "github.com/apache/arrow/go/v14/arrow/internal/debug" + "github.com/apache/arrow/go/v14/arrow/memory" + "github.com/apache/arrow/go/v14/internal/json" +) + +// Timestamp represents an immutable sequence of arrow.Timestamp values. +type Timestamp struct { + array + values []arrow.Timestamp +} + +// NewTimestampData creates a new Timestamp from Data. +func NewTimestampData(data arrow.ArrayData) *Timestamp { + a := &Timestamp{} + a.refCount = 1 + a.setData(data.(*Data)) + return a +} + +// Reset resets the array for re-use. +func (a *Timestamp) Reset(data *Data) { + a.setData(data) +} + +// Value returns the value at the specified index. +func (a *Timestamp) Value(i int) arrow.Timestamp { return a.values[i] } + +// TimestampValues returns the values. +func (a *Timestamp) TimestampValues() []arrow.Timestamp { return a.values } + +// String returns a string representation of the array. +func (a *Timestamp) String() string { + o := new(strings.Builder) + o.WriteString("[") + for i, v := range a.values { + if i > 0 { + fmt.Fprintf(o, " ") + } + switch { + case a.IsNull(i): + o.WriteString(NullValueStr) + default: + fmt.Fprintf(o, "%v", v) + } + } + o.WriteString("]") + return o.String() +} + +func (a *Timestamp) setData(data *Data) { + a.array.setData(data) + vals := data.buffers[1] + if vals != nil { + a.values = arrow.TimestampTraits.CastFromBytes(vals.Bytes()) + beg := a.array.data.offset + end := beg + a.array.data.length + a.values = a.values[beg:end] + } +} + +func (a *Timestamp) ValueStr(i int) string { + if a.IsNull(i) { + return NullValueStr + } + + dt := a.DataType().(*arrow.TimestampType) + z, _ := dt.GetZone() + return a.values[i].ToTime(dt.Unit).In(z).Format("2006-01-02 15:04:05.999999999Z0700") +} + +func (a *Timestamp) GetOneForMarshal(i int) interface{} { + if a.IsNull(i) { + return nil + } + return a.values[i].ToTime(a.DataType().(*arrow.TimestampType).Unit).Format("2006-01-02 15:04:05.999999999") +} + +func (a *Timestamp) MarshalJSON() ([]byte, error) { + vals := make([]interface{}, a.Len()) + for i := range a.values { + vals[i] = a.GetOneForMarshal(i) + } + + return json.Marshal(vals) +} + +func arrayEqualTimestamp(left, right *Timestamp) bool { + for i := 0; i < left.Len(); i++ { + if left.IsNull(i) { + continue + } + if left.Value(i) != right.Value(i) { + return false + } + } + return true +} + +type TimestampBuilder struct { + builder + + dtype *arrow.TimestampType + data *memory.Buffer + rawData []arrow.Timestamp +} + +func NewTimestampBuilder(mem memory.Allocator, dtype *arrow.TimestampType) *TimestampBuilder { + return &TimestampBuilder{builder: builder{refCount: 1, mem: mem}, dtype: dtype} +} + +func (b *TimestampBuilder) Type() arrow.DataType { return b.dtype } + +// Release decreases the reference count by 1. +// When the reference count goes to zero, the memory is freed. +func (b *TimestampBuilder) Release() { + debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases") + + if atomic.AddInt64(&b.refCount, -1) == 0 { + if b.nullBitmap != nil { + b.nullBitmap.Release() + b.nullBitmap = nil + } + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + } +} + +func (b *TimestampBuilder) AppendTime(t time.Time) { + ts, err := arrow.TimestampFromTime(t, b.dtype.Unit) + if err != nil { + panic(err) + } + b.Append(ts) +} + +func (b *TimestampBuilder) Append(v arrow.Timestamp) { + b.Reserve(1) + b.UnsafeAppend(v) +} + +func (b *TimestampBuilder) AppendNull() { + b.Reserve(1) + b.UnsafeAppendBoolToBitmap(false) +} + +func (b *TimestampBuilder) AppendNulls(n int) { + for i := 0; i < n; i++ { + b.AppendNull() + } +} + +func (b *TimestampBuilder) AppendEmptyValue() { + b.Append(0) +} + +func (b *TimestampBuilder) AppendEmptyValues(n int) { + for i := 0; i < n; i++ { + b.AppendEmptyValue() + } +} + +func (b *TimestampBuilder) UnsafeAppend(v arrow.Timestamp) { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + b.rawData[b.length] = v + b.length++ +} + +func (b *TimestampBuilder) UnsafeAppendBoolToBitmap(isValid bool) { + if isValid { + bitutil.SetBit(b.nullBitmap.Bytes(), b.length) + } else { + b.nulls++ + } + b.length++ +} + +// AppendValues will append the values in the v slice. The valid slice determines which values +// in v are valid (not null). The valid slice must either be empty or be equal in length to v. If empty, +// all values in v are appended and considered valid. +func (b *TimestampBuilder) AppendValues(v []arrow.Timestamp, valid []bool) { + if len(v) != len(valid) && len(valid) != 0 { + panic("len(v) != len(valid) && len(valid) != 0") + } + + if len(v) == 0 { + return + } + + b.Reserve(len(v)) + arrow.TimestampTraits.Copy(b.rawData[b.length:], v) + b.builder.unsafeAppendBoolsToBitmap(valid, len(v)) +} + +func (b *TimestampBuilder) init(capacity int) { + b.builder.init(capacity) + + b.data = memory.NewResizableBuffer(b.mem) + bytesN := arrow.TimestampTraits.BytesRequired(capacity) + b.data.Resize(bytesN) + b.rawData = arrow.TimestampTraits.CastFromBytes(b.data.Bytes()) +} + +// Reserve ensures there is enough space for appending n elements +// by checking the capacity and calling Resize if necessary. +func (b *TimestampBuilder) Reserve(n int) { + b.builder.reserve(n, b.Resize) +} + +// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(), +// additional memory will be allocated. If n is smaller, the allocated memory may reduced. +func (b *TimestampBuilder) Resize(n int) { + nBuilder := n + if n < minBuilderCapacity { + n = minBuilderCapacity + } + + if b.capacity == 0 { + b.init(n) + } else { + b.builder.resize(nBuilder, b.init) + b.data.Resize(arrow.TimestampTraits.BytesRequired(n)) + b.rawData = arrow.TimestampTraits.CastFromBytes(b.data.Bytes()) + } +} + +// NewArray creates a Timestamp array from the memory buffers used by the builder and resets the TimestampBuilder +// so it can be used to build a new array. +func (b *TimestampBuilder) NewArray() arrow.Array { + return b.NewTimestampArray() +} + +// NewTimestampArray creates a Timestamp array from the memory buffers used by the builder and resets the TimestampBuilder +// so it can be used to build a new array. +func (b *TimestampBuilder) NewTimestampArray() (a *Timestamp) { + data := b.newData() + a = NewTimestampData(data) + data.Release() + return +} + +func (b *TimestampBuilder) newData() (data *Data) { + bytesRequired := arrow.TimestampTraits.BytesRequired(b.length) + if bytesRequired > 0 && bytesRequired < b.data.Len() { + // trim buffers + b.data.Resize(bytesRequired) + } + data = NewData(b.dtype, b.length, []*memory.Buffer{b.nullBitmap, b.data}, nil, b.nulls, 0) + b.reset() + + if b.data != nil { + b.data.Release() + b.data = nil + b.rawData = nil + } + + return +} + +func (b *TimestampBuilder) AppendValueFromString(s string) error { + if s == NullValueStr { + b.AppendNull() + return nil + } + + loc, err := b.dtype.GetZone() + if err != nil { + return err + } + + v, _, err := arrow.TimestampFromStringInLocation(s, b.dtype.Unit, loc) + if err != nil { + b.AppendNull() + return err + } + b.Append(v) + return nil +} + +func (b *TimestampBuilder) UnmarshalOne(dec *json.Decoder) error { + t, err := dec.Token() + if err != nil { + return err + } + + switch v := t.(type) { + case nil: + b.AppendNull() + case string: + loc, _ := b.dtype.GetZone() + tm, _, err := arrow.TimestampFromStringInLocation(v, b.dtype.Unit, loc) + if err != nil { + return &json.UnmarshalTypeError{ + Value: v, + Type: reflect.TypeOf(arrow.Timestamp(0)), + Offset: dec.InputOffset(), + } + } + + b.Append(tm) + case json.Number: + n, err := v.Int64() + if err != nil { + return &json.UnmarshalTypeError{ + Value: v.String(), + Type: reflect.TypeOf(arrow.Timestamp(0)), + Offset: dec.InputOffset(), + } + } + b.Append(arrow.Timestamp(n)) + case float64: + b.Append(arrow.Timestamp(v)) + + default: + return &json.UnmarshalTypeError{ + Value: fmt.Sprint(t), + Type: reflect.TypeOf(arrow.Timestamp(0)), + Offset: dec.InputOffset(), + } + } + + return nil +} + +func (b *TimestampBuilder) Unmarshal(dec *json.Decoder) error { + for dec.More() { + if err := b.UnmarshalOne(dec); err != nil { + return err + } + } + return nil +} + +func (b *TimestampBuilder) UnmarshalJSON(data []byte) error { + dec := json.NewDecoder(bytes.NewReader(data)) + t, err := dec.Token() + if err != nil { + return err + } + + if delim, ok := t.(json.Delim); !ok || delim != '[' { + return fmt.Errorf("binary builder must unpack from json array, found %s", delim) + } + + return b.Unmarshal(dec) +} + +var ( + _ arrow.Array = (*Timestamp)(nil) + _ Builder = (*TimestampBuilder)(nil) +) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array/union.go b/vendor/github.com/apache/arrow/go/v14/arrow/array/union.go new file mode 100644 index 000000000..869355ac7 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array/union.go @@ -0,0 +1,1370 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package array + +import ( + "bytes" + "errors" + "fmt" + "math" + "reflect" + "strings" + "sync/atomic" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/bitutil" + "github.com/apache/arrow/go/v14/arrow/internal/debug" + "github.com/apache/arrow/go/v14/arrow/memory" + "github.com/apache/arrow/go/v14/internal/bitutils" + "github.com/apache/arrow/go/v14/internal/json" +) + +// Union is a convenience interface to encompass both Sparse and Dense +// union array types. +type Union interface { + arrow.Array + // NumFields returns the number of child fields in this union. + // Equivalent to len(UnionType().Fields()) + NumFields() int + // Validate returns an error if there are any issues with the lengths + // or types of the children arrays mismatching with the Type of the + // Union Array. nil is returned if there are no problems. + Validate() error + // ValidateFull runs the same checks that Validate() does, but additionally + // checks that all childIDs are valid (>= 0 || ==InvalidID) and for + // dense unions validates that all offsets are within the bounds of their + // respective child. + ValidateFull() error + // TypeCodes returns the type id buffer for the union Array, equivalent to + // Data().Buffers()[1]. Note: This will not account for any slice offset. + TypeCodes() *memory.Buffer + // RawTypeCodes returns a slice of UnionTypeCodes properly accounting for + // any slice offset. + RawTypeCodes() []arrow.UnionTypeCode + // TypeCode returns the logical type code of the value at the requested index + TypeCode(i int) arrow.UnionTypeCode + // ChildID returns the index of the physical child containing the value + // at the requested index. Equivalent to: + // + // arr.UnionType().ChildIDs()[arr.RawTypeCodes()[i+arr.Data().Offset()]] + ChildID(i int) int + // UnionType is a convenience function to retrieve the properly typed UnionType + // instead of having to call DataType() and manually assert the type. + UnionType() arrow.UnionType + // Mode returns the union mode of the underlying Array, either arrow.SparseMode + // or arrow.DenseMode. + Mode() arrow.UnionMode + // Field returns the requested child array for this union. Returns nil if a + // non-existent position is passed in. + // + // The appropriate child for an index can be retrieved with Field(ChildID(index)) + Field(pos int) arrow.Array +} + +const kMaxElems = math.MaxInt32 + +type union struct { + array + + unionType arrow.UnionType + typecodes []arrow.UnionTypeCode + + children []arrow.Array +} + +func (a *union) Retain() { + a.array.Retain() + for _, c := range a.children { + c.Retain() + } +} + +func (a *union) Release() { + a.array.Release() + for _, c := range a.children { + c.Release() + } +} + +func (a *union) NumFields() int { return len(a.unionType.Fields()) } + +func (a *union) Mode() arrow.UnionMode { return a.unionType.Mode() } + +func (a *union) UnionType() arrow.UnionType { return a.unionType } + +func (a *union) TypeCodes() *memory.Buffer { + return a.data.buffers[1] +} + +func (a *union) RawTypeCodes() []arrow.UnionTypeCode { + if a.data.length > 0 { + return a.typecodes[a.data.offset:] + } + return []arrow.UnionTypeCode{} +} + +func (a *union) TypeCode(i int) arrow.UnionTypeCode { + return a.typecodes[i+a.data.offset] +} + +func (a *union) ChildID(i int) int { + return a.unionType.ChildIDs()[a.typecodes[i+a.data.offset]] +} + +func (a *union) setData(data *Data) { + a.unionType = data.dtype.(arrow.UnionType) + debug.Assert(len(data.buffers) >= 2, "arrow/array: invalid number of union array buffers") + + if data.length > 0 { + a.typecodes = arrow.Int8Traits.CastFromBytes(data.buffers[1].Bytes()) + } else { + a.typecodes = []int8{} + } + a.children = make([]arrow.Array, len(data.childData)) + for i, child := range data.childData { + if a.unionType.Mode() == arrow.SparseMode && (data.offset != 0 || child.Len() != data.length) { + child = NewSliceData(child, int64(data.offset), int64(data.offset+data.length)) + defer child.Release() + } + a.children[i] = MakeFromData(child) + } + a.array.setData(data) +} + +func (a *union) Field(pos int) (result arrow.Array) { + if pos < 0 || pos >= len(a.children) { + return nil + } + + return a.children[pos] +} + +func (a *union) Validate() error { + fields := a.unionType.Fields() + for i, f := range fields { + fieldData := a.data.childData[i] + if a.unionType.Mode() == arrow.SparseMode && fieldData.Len() < a.data.length+a.data.offset { + return fmt.Errorf("arrow/array: sparse union child array #%d has length smaller than expected for union array (%d < %d)", + i, fieldData.Len(), a.data.length+a.data.offset) + } + + if !arrow.TypeEqual(f.Type, fieldData.DataType()) { + return fmt.Errorf("arrow/array: union child array #%d does not match type field %s vs %s", + i, fieldData.DataType(), f.Type) + } + } + return nil +} + +func (a *union) ValidateFull() error { + if err := a.Validate(); err != nil { + return err + } + + childIDs := a.unionType.ChildIDs() + codesMap := a.unionType.TypeCodes() + codes := a.RawTypeCodes() + + for i := 0; i < a.data.length; i++ { + code := codes[i] + if code < 0 || childIDs[code] == arrow.InvalidUnionChildID { + return fmt.Errorf("arrow/array: union value at position %d has invalid type id %d", i, code) + } + } + + if a.unionType.Mode() == arrow.DenseMode { + // validate offsets + + // map logical typeid to child length + var childLengths [256]int64 + for i := range a.unionType.Fields() { + childLengths[codesMap[i]] = int64(a.data.childData[i].Len()) + } + + // check offsets are in bounds + var lastOffsets [256]int64 + offsets := arrow.Int32Traits.CastFromBytes(a.data.buffers[2].Bytes())[a.data.offset:] + for i := int64(0); i < int64(a.data.length); i++ { + code := codes[i] + offset := offsets[i] + switch { + case offset < 0: + return fmt.Errorf("arrow/array: union value at position %d has negative offset %d", i, offset) + case offset >= int32(childLengths[code]): + return fmt.Errorf("arrow/array: union value at position %d has offset larger than child length (%d >= %d)", + i, offset, childLengths[code]) + case offset < int32(lastOffsets[code]): + return fmt.Errorf("arrow/array: union value at position %d has non-monotonic offset %d", i, offset) + } + lastOffsets[code] = int64(offset) + } + } + + return nil +} + +// SparseUnion represents an array where each logical value is taken from +// a single child. A buffer of 8-bit type ids indicates which child a given +// logical value is to be taken from. This is represented as the ChildID, +// which is the index into the list of children. +// +// In a sparse union, each child array will have the same length as the +// union array itself, regardless of how many values in the union actually +// refer to it. +// +// Unlike most other arrays, unions do not have a top-level validity bitmap. +type SparseUnion struct { + union +} + +// NewSparseUnion constructs a union array using the given type, length, list of +// children and buffer of typeIDs with the given offset. +func NewSparseUnion(dt *arrow.SparseUnionType, length int, children []arrow.Array, typeIDs *memory.Buffer, offset int) *SparseUnion { + childData := make([]arrow.ArrayData, len(children)) + for i, c := range children { + childData[i] = c.Data() + } + data := NewData(dt, length, []*memory.Buffer{nil, typeIDs}, childData, 0, offset) + defer data.Release() + return NewSparseUnionData(data) +} + +// NewSparseUnionData constructs a SparseUnion array from the given ArrayData object. +func NewSparseUnionData(data arrow.ArrayData) *SparseUnion { + a := &SparseUnion{} + a.refCount = 1 + a.setData(data.(*Data)) + return a +} + +// NewSparseUnionFromArrays constructs a new SparseUnion array with the provided +// values. +// +// typeIDs *must* be an INT8 array with no nulls +// len(codes) *must* be either 0 or equal to len(children). If len(codes) is 0, +// the type codes used will be sequentially numeric starting at 0. +func NewSparseUnionFromArrays(typeIDs arrow.Array, children []arrow.Array, codes ...arrow.UnionTypeCode) (*SparseUnion, error) { + return NewSparseUnionFromArraysWithFieldCodes(typeIDs, children, []string{}, codes) +} + +// NewSparseUnionFromArrayWithFields constructs a new SparseUnion array like +// NewSparseUnionFromArrays, but allows specifying the field names. Type codes +// will be auto-generated sequentially starting at 0. +// +// typeIDs *must* be an INT8 array with no nulls. +// len(fields) *must* either be 0 or equal to len(children). If len(fields) is 0, +// then the fields will be named sequentially starting at "0". +func NewSparseUnionFromArraysWithFields(typeIDs arrow.Array, children []arrow.Array, fields []string) (*SparseUnion, error) { + return NewSparseUnionFromArraysWithFieldCodes(typeIDs, children, fields, []arrow.UnionTypeCode{}) +} + +// NewSparseUnionFromArraysWithFieldCodes combines the other constructors +// for constructing a new SparseUnion array with the provided field names +// and type codes, along with children and type ids. +// +// All the requirements mentioned in NewSparseUnionFromArrays and +// NewSparseUnionFromArraysWithFields apply. +func NewSparseUnionFromArraysWithFieldCodes(typeIDs arrow.Array, children []arrow.Array, fields []string, codes []arrow.UnionTypeCode) (*SparseUnion, error) { + switch { + case typeIDs.DataType().ID() != arrow.INT8: + return nil, errors.New("arrow/array: union array type ids must be signed int8") + case typeIDs.NullN() != 0: + return nil, errors.New("arrow/array: union type ids may not have nulls") + case len(fields) > 0 && len(fields) != len(children): + return nil, errors.New("arrow/array: field names must have the same length as children") + case len(codes) > 0 && len(codes) != len(children): + return nil, errors.New("arrow/array: type codes must have same length as children") + } + + buffers := []*memory.Buffer{nil, typeIDs.Data().Buffers()[1]} + ty := arrow.SparseUnionFromArrays(children, fields, codes) + + childData := make([]arrow.ArrayData, len(children)) + for i, c := range children { + childData[i] = c.Data() + if c.Len() != typeIDs.Len() { + return nil, errors.New("arrow/array: sparse union array must have len(child) == len(typeids) for all children") + } + } + + data := NewData(ty, typeIDs.Len(), buffers, childData, 0, typeIDs.Data().Offset()) + defer data.Release() + return NewSparseUnionData(data), nil +} + +func (a *SparseUnion) setData(data *Data) { + a.union.setData(data) + debug.Assert(a.data.dtype.ID() == arrow.SPARSE_UNION, "arrow/array: invalid data type for SparseUnion") + debug.Assert(len(a.data.buffers) == 2, "arrow/array: sparse unions should have exactly 2 buffers") + debug.Assert(a.data.buffers[0] == nil, "arrow/array: validity bitmap for sparse unions should be nil") +} + +func (a *SparseUnion) GetOneForMarshal(i int) interface{} { + typeID := a.RawTypeCodes()[i] + + childID := a.ChildID(i) + data := a.Field(childID) + + if data.IsNull(i) { + return nil + } + + return []interface{}{typeID, data.GetOneForMarshal(i)} +} + +func (a *SparseUnion) MarshalJSON() ([]byte, error) { + var buf bytes.Buffer + enc := json.NewEncoder(&buf) + + buf.WriteByte('[') + for i := 0; i < a.Len(); i++ { + if i != 0 { + buf.WriteByte(',') + } + if err := enc.Encode(a.GetOneForMarshal(i)); err != nil { + return nil, err + } + } + buf.WriteByte(']') + return buf.Bytes(), nil +} + +func (a *SparseUnion) ValueStr(i int) string { + if a.IsNull(i) { + return NullValueStr + } + + val := a.GetOneForMarshal(i) + if val == nil { + // child is nil + return NullValueStr + } + + data, err := json.Marshal(val) + if err != nil { + panic(err) + } + return string(data) +} + +func (a *SparseUnion) String() string { + var b strings.Builder + b.WriteByte('[') + + fieldList := a.unionType.Fields() + for i := 0; i < a.Len(); i++ { + if i > 0 { + b.WriteString(" ") + } + + field := fieldList[a.ChildID(i)] + f := a.Field(a.ChildID(i)) + fmt.Fprintf(&b, "{%s=%v}", field.Name, f.GetOneForMarshal(i)) + } + b.WriteByte(']') + return b.String() +} + +// GetFlattenedField returns a child array, adjusting its validity bitmap +// where the union array type codes don't match. +// +// ie: the returned array will have a null in every index that it is +// not referenced by union. +func (a *SparseUnion) GetFlattenedField(mem memory.Allocator, index int) (arrow.Array, error) { + if index < 0 || index >= a.NumFields() { + return nil, fmt.Errorf("arrow/array: index out of range: %d", index) + } + + childData := a.data.childData[index] + if a.data.offset != 0 || a.data.length != childData.Len() { + childData = NewSliceData(childData, int64(a.data.offset), int64(a.data.offset+a.data.length)) + // NewSliceData doesn't break the slice reference for buffers + // since we're going to replace the null bitmap buffer we need to break the + // slice reference so that we don't affect a.children's references + newBufs := make([]*memory.Buffer, len(childData.Buffers())) + copy(newBufs, childData.(*Data).buffers) + childData.(*Data).buffers = newBufs + } else { + childData = childData.(*Data).Copy() + } + defer childData.Release() + + // synthesize a null bitmap based on the union discriminant + // make sure the bitmap has extra bits corresponding to the child's offset + flattenedNullBitmap := memory.NewResizableBuffer(mem) + flattenedNullBitmap.Resize(childData.Len() + childData.Offset()) + + var ( + childNullBitmap = childData.Buffers()[0] + childOffset = childData.Offset() + typeCode = a.unionType.TypeCodes()[index] + codes = a.RawTypeCodes() + offset int64 = 0 + ) + bitutils.GenerateBitsUnrolled(flattenedNullBitmap.Bytes(), int64(childOffset), int64(a.data.length), + func() bool { + b := codes[offset] == typeCode + offset++ + return b + }) + + if childNullBitmap != nil { + defer childNullBitmap.Release() + bitutil.BitmapAnd(flattenedNullBitmap.Bytes(), childNullBitmap.Bytes(), + int64(childOffset), int64(childOffset), flattenedNullBitmap.Bytes(), + int64(childOffset), int64(childData.Len())) + } + childData.(*Data).buffers[0] = flattenedNullBitmap + childData.(*Data).nulls = childData.Len() - bitutil.CountSetBits(flattenedNullBitmap.Bytes(), childOffset, childData.Len()) + return MakeFromData(childData), nil +} + +func arraySparseUnionEqual(l, r *SparseUnion) bool { + childIDs := l.unionType.ChildIDs() + leftCodes, rightCodes := l.RawTypeCodes(), r.RawTypeCodes() + + for i := 0; i < l.data.length; i++ { + typeID := leftCodes[i] + if typeID != rightCodes[i] { + return false + } + + childNum := childIDs[typeID] + eq := SliceEqual(l.children[childNum], int64(i), int64(i+1), + r.children[childNum], int64(i), int64(i+1)) + if !eq { + return false + } + } + return true +} + +func arraySparseUnionApproxEqual(l, r *SparseUnion, opt equalOption) bool { + childIDs := l.unionType.ChildIDs() + leftCodes, rightCodes := l.RawTypeCodes(), r.RawTypeCodes() + + for i := 0; i < l.data.length; i++ { + typeID := leftCodes[i] + if typeID != rightCodes[i] { + return false + } + + childNum := childIDs[typeID] + eq := sliceApproxEqual(l.children[childNum], int64(i+l.data.offset), int64(i+l.data.offset+1), + r.children[childNum], int64(i+r.data.offset), int64(i+r.data.offset+1), opt) + if !eq { + return false + } + } + return true +} + +// DenseUnion represents an array where each logical value is taken from +// a single child, at a specific offset. A buffer of 8-bit type ids +// indicates which child a given logical value is to be taken from and +// a buffer of 32-bit offsets indicating which physical position in the +// given child array has the logical value for that index. +// +// Unlike a sparse union, a dense union allows encoding only the child values +// which are actually referred to by the union array. This is counterbalanced +// by the additional footprint of the offsets buffer, and the additional +// indirection cost when looking up values. +// +// Unlike most other arrays, unions do not have a top-level validity bitmap. +type DenseUnion struct { + union + offsets []int32 +} + +// NewDenseUnion constructs a union array using the given type, length, list of +// children and buffers of typeIDs and offsets, with the given array offset. +func NewDenseUnion(dt *arrow.DenseUnionType, length int, children []arrow.Array, typeIDs, valueOffsets *memory.Buffer, offset int) *DenseUnion { + childData := make([]arrow.ArrayData, len(children)) + for i, c := range children { + childData[i] = c.Data() + } + + data := NewData(dt, length, []*memory.Buffer{nil, typeIDs, valueOffsets}, childData, 0, offset) + defer data.Release() + return NewDenseUnionData(data) +} + +// NewDenseUnionData constructs a DenseUnion array from the given ArrayData object. +func NewDenseUnionData(data arrow.ArrayData) *DenseUnion { + a := &DenseUnion{} + a.refCount = 1 + a.setData(data.(*Data)) + return a +} + +// NewDenseUnionFromArrays constructs a new DenseUnion array with the provided +// values. +// +// typeIDs *must* be an INT8 array with no nulls +// offsets *must* be an INT32 array with no nulls +// len(codes) *must* be either 0 or equal to len(children). If len(codes) is 0, +// the type codes used will be sequentially numeric starting at 0. +func NewDenseUnionFromArrays(typeIDs, offsets arrow.Array, children []arrow.Array, codes ...arrow.UnionTypeCode) (*DenseUnion, error) { + return NewDenseUnionFromArraysWithFieldCodes(typeIDs, offsets, children, []string{}, codes) +} + +// NewDenseUnionFromArrayWithFields constructs a new DenseUnion array like +// NewDenseUnionFromArrays, but allows specifying the field names. Type codes +// will be auto-generated sequentially starting at 0. +// +// typeIDs *must* be an INT8 array with no nulls. +// offsets *must* be an INT32 array with no nulls. +// len(fields) *must* either be 0 or equal to len(children). If len(fields) is 0, +// then the fields will be named sequentially starting at "0". +func NewDenseUnionFromArraysWithFields(typeIDs, offsets arrow.Array, children []arrow.Array, fields []string) (*DenseUnion, error) { + return NewDenseUnionFromArraysWithFieldCodes(typeIDs, offsets, children, fields, []arrow.UnionTypeCode{}) +} + +// NewDenseUnionFromArraysWithFieldCodes combines the other constructors +// for constructing a new DenseUnion array with the provided field names +// and type codes, along with children and type ids. +// +// All the requirements mentioned in NewDenseUnionFromArrays and +// NewDenseUnionFromArraysWithFields apply. +func NewDenseUnionFromArraysWithFieldCodes(typeIDs, offsets arrow.Array, children []arrow.Array, fields []string, codes []arrow.UnionTypeCode) (*DenseUnion, error) { + switch { + case offsets.DataType().ID() != arrow.INT32: + return nil, errors.New("arrow/array: union offsets must be signed int32") + case typeIDs.DataType().ID() != arrow.INT8: + return nil, errors.New("arrow/array: union type_ids must be signed int8") + case typeIDs.NullN() != 0: + return nil, errors.New("arrow/array: union typeIDs may not have nulls") + case offsets.NullN() != 0: + return nil, errors.New("arrow/array: nulls are not allowed in offsets for NewDenseUnionFromArrays*") + case len(fields) > 0 && len(fields) != len(children): + return nil, errors.New("arrow/array: fields must be the same length as children") + case len(codes) > 0 && len(codes) != len(children): + return nil, errors.New("arrow/array: typecodes must have the same length as children") + } + + ty := arrow.DenseUnionFromArrays(children, fields, codes) + buffers := []*memory.Buffer{nil, typeIDs.Data().Buffers()[1], offsets.Data().Buffers()[1]} + + childData := make([]arrow.ArrayData, len(children)) + for i, c := range children { + childData[i] = c.Data() + } + + data := NewData(ty, typeIDs.Len(), buffers, childData, 0, typeIDs.Data().Offset()) + defer data.Release() + return NewDenseUnionData(data), nil +} + +func (a *DenseUnion) ValueOffsets() *memory.Buffer { return a.data.buffers[2] } + +func (a *DenseUnion) ValueOffset(i int) int32 { return a.offsets[i+a.data.offset] } + +func (a *DenseUnion) RawValueOffsets() []int32 { return a.offsets[a.data.offset:] } + +func (a *DenseUnion) setData(data *Data) { + a.union.setData(data) + debug.Assert(a.data.dtype.ID() == arrow.DENSE_UNION, "arrow/array: invalid data type for DenseUnion") + debug.Assert(len(a.data.buffers) == 3, "arrow/array: dense unions should have exactly 3 buffers") + debug.Assert(a.data.buffers[0] == nil, "arrow/array: validity bitmap for dense unions should be nil") + + if data.length > 0 { + a.offsets = arrow.Int32Traits.CastFromBytes(a.data.buffers[2].Bytes()) + } else { + a.offsets = []int32{} + } +} + +func (a *DenseUnion) GetOneForMarshal(i int) interface{} { + typeID := a.RawTypeCodes()[i] + + childID := a.ChildID(i) + data := a.Field(childID) + + offset := int(a.RawValueOffsets()[i]) + if data.IsNull(offset) { + return nil + } + + return []interface{}{typeID, data.GetOneForMarshal(offset)} +} + +func (a *DenseUnion) MarshalJSON() ([]byte, error) { + var buf bytes.Buffer + enc := json.NewEncoder(&buf) + + buf.WriteByte('[') + for i := 0; i < a.Len(); i++ { + if i != 0 { + buf.WriteByte(',') + } + if err := enc.Encode(a.GetOneForMarshal(i)); err != nil { + return nil, err + } + } + buf.WriteByte(']') + return buf.Bytes(), nil +} + +func (a *DenseUnion) ValueStr(i int) string { + if a.IsNull(i) { + return NullValueStr + } + + val := a.GetOneForMarshal(i) + if val == nil { + // child in nil + return NullValueStr + } + + data, err := json.Marshal(val) + if err != nil { + panic(err) + } + return string(data) +} + +func (a *DenseUnion) String() string { + var b strings.Builder + b.WriteByte('[') + + offsets := a.RawValueOffsets() + + fieldList := a.unionType.Fields() + for i := 0; i < a.Len(); i++ { + if i > 0 { + b.WriteString(" ") + } + + field := fieldList[a.ChildID(i)] + f := a.Field(a.ChildID(i)) + fmt.Fprintf(&b, "{%s=%v}", field.Name, f.GetOneForMarshal(int(offsets[i]))) + } + b.WriteByte(']') + return b.String() +} + +func arrayDenseUnionEqual(l, r *DenseUnion) bool { + childIDs := l.unionType.ChildIDs() + leftCodes, rightCodes := l.RawTypeCodes(), r.RawTypeCodes() + leftOffsets, rightOffsets := l.RawValueOffsets(), r.RawValueOffsets() + + for i := 0; i < l.data.length; i++ { + typeID := leftCodes[i] + if typeID != rightCodes[i] { + return false + } + + childNum := childIDs[typeID] + eq := SliceEqual(l.children[childNum], int64(leftOffsets[i]), int64(leftOffsets[i]+1), + r.children[childNum], int64(rightOffsets[i]), int64(rightOffsets[i]+1)) + if !eq { + return false + } + } + return true +} + +func arrayDenseUnionApproxEqual(l, r *DenseUnion, opt equalOption) bool { + childIDs := l.unionType.ChildIDs() + leftCodes, rightCodes := l.RawTypeCodes(), r.RawTypeCodes() + leftOffsets, rightOffsets := l.RawValueOffsets(), r.RawValueOffsets() + + for i := 0; i < l.data.length; i++ { + typeID := leftCodes[i] + if typeID != rightCodes[i] { + return false + } + + childNum := childIDs[typeID] + eq := sliceApproxEqual(l.children[childNum], int64(leftOffsets[i]), int64(leftOffsets[i]+1), + r.children[childNum], int64(rightOffsets[i]), int64(rightOffsets[i]+1), opt) + if !eq { + return false + } + } + return true +} + +// UnionBuilder is a convenience interface for building Union arrays of +// either Dense or Sparse mode. +type UnionBuilder interface { + Builder + // AppendChild allows constructing the union type on the fly by making new + // new array builder available to the union builder. The type code (index) + // of the new child is returned, which should be passed to the Append method + // when adding a new element to the union array. + AppendChild(newChild Builder, fieldName string) (newCode arrow.UnionTypeCode) + // Append adds an element to the UnionArray indicating which typecode the + // new element should use. This *must* be followed up by an append to the + // appropriate child builder. + Append(arrow.UnionTypeCode) + // Mode returns what kind of Union is being built, either arrow.SparseMode + // or arrow.DenseMode + Mode() arrow.UnionMode + // Child returns the builder for the requested child index. + // If an invalid index is requested (e.g. <0 or >len(children)) + // then this will panic. + Child(idx int) Builder +} + +type unionBuilder struct { + builder + + childFields []arrow.Field + codes []arrow.UnionTypeCode + mode arrow.UnionMode + + children []Builder + typeIDtoBuilder []Builder + typeIDtoChildID []int + // for all typeID < denseTypeID, typeIDtoBuilder[typeID] != nil + denseTypeID arrow.UnionTypeCode + typesBuilder *int8BufferBuilder +} + +func newUnionBuilder(mem memory.Allocator, children []Builder, typ arrow.UnionType) unionBuilder { + if children == nil { + children = make([]Builder, 0) + } + b := unionBuilder{ + builder: builder{refCount: 1, mem: mem}, + mode: typ.Mode(), + codes: typ.TypeCodes(), + children: children, + typeIDtoChildID: make([]int, int(typ.MaxTypeCode())+1), // convert to int as int8(127) +1 panics + typeIDtoBuilder: make([]Builder, int(typ.MaxTypeCode())+1), // convert to int as int8(127) +1 panics + childFields: make([]arrow.Field, len(children)), + typesBuilder: newInt8BufferBuilder(mem), + } + + b.typeIDtoChildID[0] = arrow.InvalidUnionChildID + for i := 1; i < len(b.typeIDtoChildID); i *= 2 { + copy(b.typeIDtoChildID[i:], b.typeIDtoChildID[:i]) + } + + debug.Assert(len(children) == len(typ.TypeCodes()), "mismatched typecodes and children") + debug.Assert(len(b.typeIDtoBuilder)-1 <= int(arrow.MaxUnionTypeCode), "too many typeids") + + copy(b.childFields, typ.Fields()) + for i, c := range children { + c.Retain() + typeID := typ.TypeCodes()[i] + b.typeIDtoChildID[typeID] = i + b.typeIDtoBuilder[typeID] = c + } + + return b +} + +func (b *unionBuilder) NumChildren() int { + return len(b.children) +} + +func (b *unionBuilder) Child(idx int) Builder { + if idx < 0 || idx > len(b.children) { + panic("arrow/array: invalid child index for union builder") + } + return b.children[idx] +} + +// Len returns the current number of elements in the builder. +func (b *unionBuilder) Len() int { return b.typesBuilder.Len() } + +func (b *unionBuilder) Mode() arrow.UnionMode { return b.mode } + +func (b *unionBuilder) reserve(elements int, resize func(int)) { + // union has no null bitmap, ever so we can skip that handling + if b.length+elements > b.capacity { + b.capacity = bitutil.NextPowerOf2(b.length + elements) + resize(b.capacity) + } +} + +func (b *unionBuilder) Release() { + debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases") + + if atomic.AddInt64(&b.refCount, -1) == 0 { + for _, c := range b.children { + c.Release() + } + b.typesBuilder.Release() + } +} + +func (b *unionBuilder) Type() arrow.DataType { + fields := make([]arrow.Field, len(b.childFields)) + for i, f := range b.childFields { + fields[i] = f + fields[i].Type = b.children[i].Type() + } + + switch b.mode { + case arrow.SparseMode: + return arrow.SparseUnionOf(fields, b.codes) + case arrow.DenseMode: + return arrow.DenseUnionOf(fields, b.codes) + default: + panic("invalid union builder mode") + } +} + +func (b *unionBuilder) AppendChild(newChild Builder, fieldName string) arrow.UnionTypeCode { + newChild.Retain() + b.children = append(b.children, newChild) + newType := b.nextTypeID() + + b.typeIDtoChildID[newType] = len(b.children) - 1 + b.typeIDtoBuilder[newType] = newChild + b.childFields = append(b.childFields, arrow.Field{Name: fieldName, Nullable: true}) + b.codes = append(b.codes, newType) + + return newType +} + +func (b *unionBuilder) nextTypeID() arrow.UnionTypeCode { + // find typeID such that typeIDtoBuilder[typeID] == nil + // use that for the new child. Start searching at denseTypeID + // since typeIDtoBuilder is densely packed up at least to denseTypeID + for ; int(b.denseTypeID) < len(b.typeIDtoBuilder); b.denseTypeID++ { + if b.typeIDtoBuilder[b.denseTypeID] == nil { + id := b.denseTypeID + b.denseTypeID++ + return id + } + } + + debug.Assert(len(b.typeIDtoBuilder) < int(arrow.MaxUnionTypeCode), "too many children typeids") + // typeIDtoBuilder is already densely packed, so just append the new child + b.typeIDtoBuilder = append(b.typeIDtoBuilder, nil) + b.typeIDtoChildID = append(b.typeIDtoChildID, arrow.InvalidUnionChildID) + id := b.denseTypeID + b.denseTypeID++ + return id + +} + +func (b *unionBuilder) newData() *Data { + length := b.typesBuilder.Len() + typesBuffer := b.typesBuilder.Finish() + defer typesBuffer.Release() + childData := make([]arrow.ArrayData, len(b.children)) + for i, b := range b.children { + childData[i] = b.newData() + defer childData[i].Release() + } + + return NewData(b.Type(), length, []*memory.Buffer{nil, typesBuffer}, childData, 0, 0) +} + +// SparseUnionBuilder is used to build a Sparse Union array using the Append +// methods. You can also add new types to the union on the fly by using +// AppendChild. +// +// Keep in mind: All children of a SparseUnion should be the same length +// as the union itself. If you add new children with AppendChild, ensure +// that they have the correct number of preceding elements that have been +// added to the builder beforehand. +type SparseUnionBuilder struct { + unionBuilder +} + +// NewEmptySparseUnionBuilder is a helper to construct a SparseUnionBuilder +// without having to predefine the union types. It creates a builder with no +// children and AppendChild will have to be called before appending any +// elements to this builder. +func NewEmptySparseUnionBuilder(mem memory.Allocator) *SparseUnionBuilder { + return &SparseUnionBuilder{ + unionBuilder: newUnionBuilder(mem, nil, arrow.SparseUnionOf([]arrow.Field{}, []arrow.UnionTypeCode{})), + } +} + +// NewSparseUnionBuilder constructs a new SparseUnionBuilder with the provided +// children and type codes. Builders will be constructed for each child +// using the fields in typ +func NewSparseUnionBuilder(mem memory.Allocator, typ *arrow.SparseUnionType) *SparseUnionBuilder { + children := make([]Builder, len(typ.Fields())) + for i, f := range typ.Fields() { + children[i] = NewBuilder(mem, f.Type) + defer children[i].Release() + } + return NewSparseUnionBuilderWithBuilders(mem, typ, children) +} + +// NewSparseUnionWithBuilders returns a new SparseUnionBuilder using the +// provided type and builders. +func NewSparseUnionBuilderWithBuilders(mem memory.Allocator, typ *arrow.SparseUnionType, children []Builder) *SparseUnionBuilder { + return &SparseUnionBuilder{ + unionBuilder: newUnionBuilder(mem, children, typ), + } +} + +func (b *SparseUnionBuilder) Reserve(n int) { + b.reserve(n, b.Resize) +} + +func (b *SparseUnionBuilder) Resize(n int) { + b.typesBuilder.resize(n) +} + +// AppendNull will append a null to the first child and an empty value +// (implementation-defined) to the rest of the children. +func (b *SparseUnionBuilder) AppendNull() { + firstChildCode := b.codes[0] + b.typesBuilder.AppendValue(firstChildCode) + b.typeIDtoBuilder[firstChildCode].AppendNull() + for _, c := range b.codes[1:] { + b.typeIDtoBuilder[c].AppendEmptyValue() + } +} + +// AppendNulls is identical to calling AppendNull() n times, except +// it will pre-allocate with reserve for all the nulls beforehand. +func (b *SparseUnionBuilder) AppendNulls(n int) { + firstChildCode := b.codes[0] + b.Reserve(n) + for _, c := range b.codes { + b.typeIDtoBuilder[c].Reserve(n) + } + for i := 0; i < n; i++ { + b.typesBuilder.AppendValue(firstChildCode) + b.typeIDtoBuilder[firstChildCode].AppendNull() + for _, c := range b.codes[1:] { + b.typeIDtoBuilder[c].AppendEmptyValue() + } + } +} + +// AppendEmptyValue appends an empty value (implementation defined) +// to each child, and appends the type of the first typecode to the typeid +// buffer. +func (b *SparseUnionBuilder) AppendEmptyValue() { + b.typesBuilder.AppendValue(b.codes[0]) + for _, c := range b.codes { + b.typeIDtoBuilder[c].AppendEmptyValue() + } +} + +// AppendEmptyValues is identical to calling AppendEmptyValue() n times, +// except it pre-allocates first so it is more efficient. +func (b *SparseUnionBuilder) AppendEmptyValues(n int) { + b.Reserve(n) + firstChildCode := b.codes[0] + for _, c := range b.codes { + b.typeIDtoBuilder[c].Reserve(n) + } + for i := 0; i < n; i++ { + b.typesBuilder.AppendValue(firstChildCode) + for _, c := range b.codes { + b.typeIDtoBuilder[c].AppendEmptyValue() + } + } +} + +// Append appends an element to the UnionArray and must be followed up +// by an append to the appropriate child builder. The parameter should +// be the type id of the child to which the next value will be appended. +// +// After appending to the corresponding child builder, all other child +// builders should have a null or empty value appended to them (although +// this is not enfoced and any value is theoretically allowed and will be +// ignored). +func (b *SparseUnionBuilder) Append(nextType arrow.UnionTypeCode) { + b.typesBuilder.AppendValue(nextType) +} + +func (b *SparseUnionBuilder) NewArray() arrow.Array { + return b.NewSparseUnionArray() +} + +func (b *SparseUnionBuilder) NewSparseUnionArray() (a *SparseUnion) { + data := b.newData() + a = NewSparseUnionData(data) + data.Release() + return +} + +func (b *SparseUnionBuilder) UnmarshalJSON(data []byte) (err error) { + dec := json.NewDecoder(bytes.NewReader(data)) + t, err := dec.Token() + if err != nil { + return err + } + + if delim, ok := t.(json.Delim); !ok || delim != '[' { + return fmt.Errorf("sparse union builder must unpack from json array, found %s", t) + } + return b.Unmarshal(dec) +} + +func (b *SparseUnionBuilder) Unmarshal(dec *json.Decoder) error { + for dec.More() { + if err := b.UnmarshalOne(dec); err != nil { + return err + } + } + return nil +} + +func (b *SparseUnionBuilder) AppendValueFromString(s string) error { + if s == NullValueStr { + b.AppendNull() + return nil + } + dec := json.NewDecoder(strings.NewReader(s)) + return b.UnmarshalOne(dec) +} + +func (b *SparseUnionBuilder) UnmarshalOne(dec *json.Decoder) error { + t, err := dec.Token() + if err != nil { + return err + } + + switch t { + case json.Delim('['): + // should be [type_id, Value] + typeID, err := dec.Token() + if err != nil { + return err + } + + var typeCode int8 + + switch tid := typeID.(type) { + case json.Number: + id, err := tid.Int64() + if err != nil { + return err + } + typeCode = int8(id) + case float64: + if tid != float64(int64(tid)) { + return &json.UnmarshalTypeError{ + Offset: dec.InputOffset(), + Type: reflect.TypeOf(int8(0)), + Struct: fmt.Sprint(b.Type()), + Value: "float", + } + } + typeCode = int8(tid) + } + + childNum := b.typeIDtoChildID[typeCode] + if childNum == arrow.InvalidUnionChildID { + return &json.UnmarshalTypeError{ + Offset: dec.InputOffset(), + Value: "invalid type code", + } + } + + for i, c := range b.children { + if i != childNum { + c.AppendNull() + } + } + + b.Append(typeCode) + if err := b.children[childNum].UnmarshalOne(dec); err != nil { + return err + } + + endArr, err := dec.Token() + if err != nil { + return err + } + + if endArr != json.Delim(']') { + return &json.UnmarshalTypeError{ + Offset: dec.InputOffset(), + Value: "union value array should have exactly 2 elements", + } + } + case nil: + b.AppendNull() + default: + return &json.UnmarshalTypeError{ + Offset: dec.InputOffset(), + Value: fmt.Sprint(t), + Struct: fmt.Sprint(b.Type()), + } + } + return nil +} + +// DenseUnionBuilder is used to build a Dense Union array using the Append +// methods. You can also add new types to the union on the fly by using +// AppendChild. +type DenseUnionBuilder struct { + unionBuilder + + offsetsBuilder *int32BufferBuilder +} + +// NewEmptyDenseUnionBuilder is a helper to construct a DenseUnionBuilder +// without having to predefine the union types. It creates a builder with no +// children and AppendChild will have to be called before appending any +// elements to this builder. +func NewEmptyDenseUnionBuilder(mem memory.Allocator) *DenseUnionBuilder { + return &DenseUnionBuilder{ + unionBuilder: newUnionBuilder(mem, nil, arrow.DenseUnionOf([]arrow.Field{}, []arrow.UnionTypeCode{})), + offsetsBuilder: newInt32BufferBuilder(mem), + } +} + +// NewDenseUnionBuilder constructs a new DenseUnionBuilder with the provided +// children and type codes. Builders will be constructed for each child +// using the fields in typ +func NewDenseUnionBuilder(mem memory.Allocator, typ *arrow.DenseUnionType) *DenseUnionBuilder { + children := make([]Builder, 0, len(typ.Fields())) + defer func() { + for _, child := range children { + child.Release() + } + }() + + for _, f := range typ.Fields() { + children = append(children, NewBuilder(mem, f.Type)) + } + return NewDenseUnionBuilderWithBuilders(mem, typ, children) +} + +// NewDenseUnionWithBuilders returns a new DenseUnionBuilder using the +// provided type and builders. +func NewDenseUnionBuilderWithBuilders(mem memory.Allocator, typ *arrow.DenseUnionType, children []Builder) *DenseUnionBuilder { + return &DenseUnionBuilder{ + unionBuilder: newUnionBuilder(mem, children, typ), + offsetsBuilder: newInt32BufferBuilder(mem), + } +} + +func (b *DenseUnionBuilder) Reserve(n int) { + b.reserve(n, b.Resize) +} + +func (b *DenseUnionBuilder) Resize(n int) { + b.typesBuilder.resize(n) + b.offsetsBuilder.resize(n * arrow.Int32SizeBytes) +} + +// AppendNull will only append a null value arbitrarily to the first child +// and use that offset for this element of the array. +func (b *DenseUnionBuilder) AppendNull() { + firstChildCode := b.codes[0] + childBuilder := b.typeIDtoBuilder[firstChildCode] + b.typesBuilder.AppendValue(firstChildCode) + b.offsetsBuilder.AppendValue(int32(childBuilder.Len())) + childBuilder.AppendNull() +} + +// AppendNulls will only append a single null arbitrarily to the first child +// and use the same offset multiple times to point to it. The result is that +// for a DenseUnion this is more efficient than calling AppendNull multiple +// times in a loop +func (b *DenseUnionBuilder) AppendNulls(n int) { + // only append 1 null to the child builder, use the same offset twice + firstChildCode := b.codes[0] + childBuilder := b.typeIDtoBuilder[firstChildCode] + b.Reserve(n) + for i := 0; i < n; i++ { + b.typesBuilder.AppendValue(firstChildCode) + b.offsetsBuilder.AppendValue(int32(childBuilder.Len())) + } + // only append a single null to the child builder, the offsets all refer to the same value + childBuilder.AppendNull() +} + +// AppendEmptyValue only appends an empty value arbitrarily to the first child, +// and then uses that offset to identify the value. +func (b *DenseUnionBuilder) AppendEmptyValue() { + firstChildCode := b.codes[0] + childBuilder := b.typeIDtoBuilder[firstChildCode] + b.typesBuilder.AppendValue(firstChildCode) + b.offsetsBuilder.AppendValue(int32(childBuilder.Len())) + childBuilder.AppendEmptyValue() +} + +// AppendEmptyValues, like AppendNulls, will only append a single empty value +// (implementation defined) to the first child arbitrarily, and then point +// at that value using the offsets n times. That makes this more efficient +// than calling AppendEmptyValue multiple times. +func (b *DenseUnionBuilder) AppendEmptyValues(n int) { + // only append 1 null to the child builder, use the same offset twice + firstChildCode := b.codes[0] + childBuilder := b.typeIDtoBuilder[firstChildCode] + b.Reserve(n) + for i := 0; i < n; i++ { + b.typesBuilder.AppendValue(firstChildCode) + b.offsetsBuilder.AppendValue(int32(childBuilder.Len())) + } + // only append a single empty value to the child builder, the offsets all + // refer to the same value + childBuilder.AppendEmptyValue() +} + +// Append appends the necessary offset and type code to the builder +// and must be followed up with an append to the appropriate child builder +func (b *DenseUnionBuilder) Append(nextType arrow.UnionTypeCode) { + b.typesBuilder.AppendValue(nextType) + bldr := b.typeIDtoBuilder[nextType] + if bldr.Len() == kMaxElems { + panic("a dense UnionArray cannot contain more than 2^31 - 1 elements from a single child") + } + + b.offsetsBuilder.AppendValue(int32(bldr.Len())) +} + +func (b *DenseUnionBuilder) Release() { + debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases") + + if atomic.AddInt64(&b.refCount, -1) == 0 { + for _, c := range b.children { + c.Release() + } + b.typesBuilder.Release() + b.offsetsBuilder.Release() + } +} + +func (b *DenseUnionBuilder) newData() *Data { + data := b.unionBuilder.newData() + data.buffers = append(data.buffers, b.offsetsBuilder.Finish()) + return data +} + +func (b *DenseUnionBuilder) NewArray() arrow.Array { + return b.NewDenseUnionArray() +} + +func (b *DenseUnionBuilder) NewDenseUnionArray() (a *DenseUnion) { + data := b.newData() + a = NewDenseUnionData(data) + data.Release() + return +} + +func (b *DenseUnionBuilder) UnmarshalJSON(data []byte) (err error) { + dec := json.NewDecoder(bytes.NewReader(data)) + t, err := dec.Token() + if err != nil { + return err + } + + if delim, ok := t.(json.Delim); !ok || delim != '[' { + return fmt.Errorf("dense union builder must unpack from json array, found %s", t) + } + return b.Unmarshal(dec) +} + +func (b *DenseUnionBuilder) Unmarshal(dec *json.Decoder) error { + for dec.More() { + if err := b.UnmarshalOne(dec); err != nil { + return err + } + } + return nil +} + +func (d *DenseUnionBuilder) AppendValueFromString(s string) error { + if s == NullValueStr { + d.AppendNull() + return nil + } + dec := json.NewDecoder(strings.NewReader(s)) + return d.UnmarshalOne(dec) +} + +func (b *DenseUnionBuilder) UnmarshalOne(dec *json.Decoder) error { + t, err := dec.Token() + if err != nil { + return err + } + + switch t { + case json.Delim('['): + // should be [type_id, Value] + typeID, err := dec.Token() + if err != nil { + return err + } + + var typeCode int8 + + switch tid := typeID.(type) { + case json.Number: + id, err := tid.Int64() + if err != nil { + return err + } + typeCode = int8(id) + case float64: + if tid != float64(int64(tid)) { + return &json.UnmarshalTypeError{ + Offset: dec.InputOffset(), + Type: reflect.TypeOf(int8(0)), + Struct: fmt.Sprint(b.Type()), + Value: "float", + } + } + typeCode = int8(tid) + } + + childNum := b.typeIDtoChildID[typeCode] + if childNum == arrow.InvalidUnionChildID { + return &json.UnmarshalTypeError{ + Offset: dec.InputOffset(), + Value: "invalid type code", + } + } + + b.Append(typeCode) + if err := b.children[childNum].UnmarshalOne(dec); err != nil { + return err + } + + endArr, err := dec.Token() + if err != nil { + return err + } + + if endArr != json.Delim(']') { + return &json.UnmarshalTypeError{ + Offset: dec.InputOffset(), + Value: "union value array should have exactly 2 elements", + } + } + case nil: + b.AppendNull() + default: + return &json.UnmarshalTypeError{ + Offset: dec.InputOffset(), + Value: fmt.Sprint(t), + Struct: fmt.Sprint(b.Type()), + } + } + return nil +} + +var ( + _ arrow.Array = (*SparseUnion)(nil) + _ arrow.Array = (*DenseUnion)(nil) + _ Union = (*SparseUnion)(nil) + _ Union = (*DenseUnion)(nil) + _ Builder = (*SparseUnionBuilder)(nil) + _ Builder = (*DenseUnionBuilder)(nil) + _ UnionBuilder = (*SparseUnionBuilder)(nil) + _ UnionBuilder = (*DenseUnionBuilder)(nil) +) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/array/util.go b/vendor/github.com/apache/arrow/go/v14/arrow/array/util.go new file mode 100644 index 000000000..54d15a809 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/array/util.go @@ -0,0 +1,523 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package array + +import ( + "errors" + "fmt" + "io" + "strings" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/bitutil" + "github.com/apache/arrow/go/v14/arrow/memory" + "github.com/apache/arrow/go/v14/internal/hashing" + "github.com/apache/arrow/go/v14/internal/json" +) + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +type fromJSONCfg struct { + multiDocument bool + startOffset int64 + useNumber bool +} + +type FromJSONOption func(*fromJSONCfg) + +func WithMultipleDocs() FromJSONOption { + return func(c *fromJSONCfg) { + c.multiDocument = true + } +} + +// WithStartOffset attempts to start decoding from the reader at the offset +// passed in. If using this option the reader must fulfill the io.ReadSeeker +// interface, or else an error will be returned. +// +// It will call Seek(off, io.SeekStart) on the reader +func WithStartOffset(off int64) FromJSONOption { + return func(c *fromJSONCfg) { + c.startOffset = off + } +} + +// WithUseNumber enables the 'UseNumber' option on the json decoder, using +// the json.Number type instead of assuming float64 for numbers. This is critical +// if you have numbers that are larger than what can fit into the 53 bits of +// an IEEE float64 mantissa and want to preserve its value. +func WithUseNumber() FromJSONOption { + return func(c *fromJSONCfg) { + c.useNumber = true + } +} + +// FromJSON creates an arrow.Array from a corresponding JSON stream and defined data type. If the types in the +// json do not match the type provided, it will return errors. This is *not* the integration test format +// and should not be used as such. This intended to be used by consumers more similarly to the current exposing of +// the csv reader/writer. It also returns the input offset in the reader where it finished decoding since buffering +// by the decoder could leave the reader's cursor past where the parsing finished if attempting to parse multiple json +// arrays from one stream. +// +// All the Array types implement json.Marshaller and thus can be written to json +// using the json.Marshal function +// +// The JSON provided must be formatted in one of two ways: +// +// Default: the top level of the json must be a list which matches the type specified exactly +// Example: `[1, 2, 3, 4, 5]` for any integer type or `[[...], null, [], .....]` for a List type +// Struct arrays are represented a list of objects: `[{"foo": 1, "bar": "moo"}, {"foo": 5, "bar": "baz"}]` +// +// Using WithMultipleDocs: +// If the JSON provided is multiple newline separated json documents, then use this option +// and each json document will be treated as a single row of the array. This is most useful for record batches +// and interacting with other processes that use json. For example: +// `{"col1": 1, "col2": "row1", "col3": ...}\n{"col1": 2, "col2": "row2", "col3": ...}\n.....` +// +// Duration values get formated upon marshalling as a string consisting of their numeric +// value followed by the unit suffix such as "10s" for a value of 10 and unit of Seconds. +// with "ms" for millisecond, "us" for microsecond, and "ns" for nanosecond as the suffixes. +// Unmarshalling duration values is more permissive since it first tries to use Go's +// time.ParseDuration function which means it allows values in the form 3h25m0.3s in addition +// to the same values which are output. +// +// Interval types are marshalled / unmarshalled as follows: +// +// MonthInterval is marshalled as an object with the format: +// { "months": #} +// DayTimeInterval is marshalled using Go's regular marshalling of structs: +// { "days": #, "milliseconds": # } +// MonthDayNanoInterval values are marshalled the same as DayTime using Go's struct marshalling: +// { "months": #, "days": #, "nanoseconds": # } +// +// Times use a format of HH:MM or HH:MM:SS[.zzz] where the fractions of a second cannot +// exceed the precision allowed by the time unit, otherwise unmarshalling will error. +// +// # Dates use YYYY-MM-DD format +// +// Timestamps use RFC3339Nano format except without a timezone, all of the following are valid: +// +// YYYY-MM-DD +// YYYY-MM-DD[T]HH +// YYYY-MM-DD[T]HH:MM +// YYYY-MM-DD[T]HH:MM:SS[.zzzzzzzzzz] +// +// The fractions of a second cannot exceed the precision allowed by the timeunit of the datatype. +// +// When processing structs as objects order of keys does not matter, but keys cannot be repeated. +func FromJSON(mem memory.Allocator, dt arrow.DataType, r io.Reader, opts ...FromJSONOption) (arr arrow.Array, offset int64, err error) { + var cfg fromJSONCfg + for _, o := range opts { + o(&cfg) + } + + if cfg.startOffset != 0 { + seeker, ok := r.(io.ReadSeeker) + if !ok { + return nil, 0, errors.New("using StartOffset option requires reader to be a ReadSeeker, cannot seek") + } + + seeker.Seek(cfg.startOffset, io.SeekStart) + } + + bldr := NewBuilder(mem, dt) + defer bldr.Release() + + dec := json.NewDecoder(r) + defer func() { + if errors.Is(err, io.EOF) { + err = fmt.Errorf("failed parsing json: %w", io.ErrUnexpectedEOF) + } + }() + + if cfg.useNumber { + dec.UseNumber() + } + + if !cfg.multiDocument { + t, err := dec.Token() + if err != nil { + return nil, dec.InputOffset(), err + } + + if delim, ok := t.(json.Delim); !ok || delim != '[' { + return nil, dec.InputOffset(), fmt.Errorf("json doc must be an array, found %s", delim) + } + } + + if err = bldr.Unmarshal(dec); err != nil { + return nil, dec.InputOffset(), err + } + + if !cfg.multiDocument { + // consume the last ']' + if _, err = dec.Token(); err != nil { + return nil, dec.InputOffset(), err + } + } + + return bldr.NewArray(), dec.InputOffset(), nil +} + +// RecordToStructArray constructs a struct array from the columns of the record batch +// by referencing them, zero-copy. +func RecordToStructArray(rec arrow.Record) *Struct { + cols := make([]arrow.ArrayData, rec.NumCols()) + for i, c := range rec.Columns() { + cols[i] = c.Data() + } + + data := NewData(arrow.StructOf(rec.Schema().Fields()...), int(rec.NumRows()), []*memory.Buffer{nil}, cols, 0, 0) + defer data.Release() + + return NewStructData(data) +} + +// RecordFromStructArray is a convenience function for converting a struct array into +// a record batch without copying the data. If the passed in schema is nil, the fields +// of the struct will be used to define the record batch. Otherwise the passed in +// schema will be used to create the record batch. If passed in, the schema must match +// the fields of the struct column. +func RecordFromStructArray(in *Struct, schema *arrow.Schema) arrow.Record { + if schema == nil { + schema = arrow.NewSchema(in.DataType().(*arrow.StructType).Fields(), nil) + } + + return NewRecord(schema, in.fields, int64(in.Len())) +} + +// RecordFromJSON creates a record batch from JSON data. See array.FromJSON for the details +// of formatting and logic. +// +// A record batch from JSON is equivalent to reading a struct array in from json and then +// converting it to a record batch. +func RecordFromJSON(mem memory.Allocator, schema *arrow.Schema, r io.Reader, opts ...FromJSONOption) (arrow.Record, int64, error) { + st := arrow.StructOf(schema.Fields()...) + arr, off, err := FromJSON(mem, st, r, opts...) + if err != nil { + return nil, off, err + } + defer arr.Release() + + return RecordFromStructArray(arr.(*Struct), schema), off, nil +} + +// RecordToJSON writes out the given record following the format of each row is a single object +// on a single line of the output. +func RecordToJSON(rec arrow.Record, w io.Writer) error { + enc := json.NewEncoder(w) + + fields := rec.Schema().Fields() + + cols := make(map[string]interface{}) + for i := 0; int64(i) < rec.NumRows(); i++ { + for j, c := range rec.Columns() { + cols[fields[j].Name] = c.GetOneForMarshal(i) + } + if err := enc.Encode(cols); err != nil { + return err + } + } + return nil +} + +func TableFromJSON(mem memory.Allocator, sc *arrow.Schema, recJSON []string, opt ...FromJSONOption) (arrow.Table, error) { + batches := make([]arrow.Record, len(recJSON)) + for i, batchJSON := range recJSON { + batch, _, err := RecordFromJSON(mem, sc, strings.NewReader(batchJSON), opt...) + if err != nil { + return nil, err + } + defer batch.Release() + batches[i] = batch + } + return NewTableFromRecords(sc, batches), nil +} + +func GetDictArrayData(mem memory.Allocator, valueType arrow.DataType, memoTable hashing.MemoTable, startOffset int) (*Data, error) { + dictLen := memoTable.Size() - startOffset + buffers := []*memory.Buffer{nil, nil} + + buffers[1] = memory.NewResizableBuffer(mem) + defer buffers[1].Release() + + switch tbl := memoTable.(type) { + case hashing.NumericMemoTable: + nbytes := tbl.TypeTraits().BytesRequired(dictLen) + buffers[1].Resize(nbytes) + tbl.WriteOutSubset(startOffset, buffers[1].Bytes()) + case *hashing.BinaryMemoTable: + switch valueType.ID() { + case arrow.BINARY, arrow.STRING: + buffers = append(buffers, memory.NewResizableBuffer(mem)) + defer buffers[2].Release() + + buffers[1].Resize(arrow.Int32Traits.BytesRequired(dictLen + 1)) + offsets := arrow.Int32Traits.CastFromBytes(buffers[1].Bytes()) + tbl.CopyOffsetsSubset(startOffset, offsets) + + valuesz := offsets[len(offsets)-1] - offsets[0] + buffers[2].Resize(int(valuesz)) + tbl.CopyValuesSubset(startOffset, buffers[2].Bytes()) + case arrow.LARGE_BINARY, arrow.LARGE_STRING: + buffers = append(buffers, memory.NewResizableBuffer(mem)) + defer buffers[2].Release() + + buffers[1].Resize(arrow.Int64Traits.BytesRequired(dictLen + 1)) + offsets := arrow.Int64Traits.CastFromBytes(buffers[1].Bytes()) + tbl.CopyLargeOffsetsSubset(startOffset, offsets) + + valuesz := offsets[len(offsets)-1] - offsets[0] + buffers[2].Resize(int(valuesz)) + tbl.CopyValuesSubset(startOffset, buffers[2].Bytes()) + default: // fixed size + bw := int(bitutil.BytesForBits(int64(valueType.(arrow.FixedWidthDataType).BitWidth()))) + buffers[1].Resize(dictLen * bw) + tbl.CopyFixedWidthValues(startOffset, bw, buffers[1].Bytes()) + } + default: + return nil, fmt.Errorf("arrow/array: dictionary unifier unimplemented type: %s", valueType) + } + + var nullcount int + if idx, ok := memoTable.GetNull(); ok && idx >= startOffset { + buffers[0] = memory.NewResizableBuffer(mem) + defer buffers[0].Release() + nullcount = 1 + buffers[0].Resize(int(bitutil.BytesForBits(int64(dictLen)))) + memory.Set(buffers[0].Bytes(), 0xFF) + bitutil.ClearBit(buffers[0].Bytes(), idx) + } + + return NewData(valueType, dictLen, buffers, nil, nullcount, 0), nil +} + +func DictArrayFromJSON(mem memory.Allocator, dt *arrow.DictionaryType, indicesJSON, dictJSON string) (arrow.Array, error) { + indices, _, err := FromJSON(mem, dt.IndexType, strings.NewReader(indicesJSON)) + if err != nil { + return nil, err + } + defer indices.Release() + + dict, _, err := FromJSON(mem, dt.ValueType, strings.NewReader(dictJSON)) + if err != nil { + return nil, err + } + defer dict.Release() + + return NewDictionaryArray(dt, indices, dict), nil +} + +func ChunkedFromJSON(mem memory.Allocator, dt arrow.DataType, chunkStrs []string, opts ...FromJSONOption) (*arrow.Chunked, error) { + chunks := make([]arrow.Array, len(chunkStrs)) + defer func() { + for _, c := range chunks { + if c != nil { + c.Release() + } + } + }() + + var err error + for i, c := range chunkStrs { + chunks[i], _, err = FromJSON(mem, dt, strings.NewReader(c), opts...) + if err != nil { + return nil, err + } + } + + return arrow.NewChunked(dt, chunks), nil +} + +func getMaxBufferLen(dt arrow.DataType, length int) int { + bufferLen := int(bitutil.BytesForBits(int64(length))) + + maxOf := func(bl int) int { + if bl > bufferLen { + return bl + } + return bufferLen + } + + switch dt := dt.(type) { + case *arrow.DictionaryType: + bufferLen = maxOf(getMaxBufferLen(dt.ValueType, length)) + return maxOf(getMaxBufferLen(dt.IndexType, length)) + case *arrow.FixedSizeBinaryType: + return maxOf(dt.ByteWidth * length) + case arrow.FixedWidthDataType: + return maxOf(int(bitutil.BytesForBits(int64(dt.BitWidth()))) * length) + case *arrow.StructType: + for _, f := range dt.Fields() { + bufferLen = maxOf(getMaxBufferLen(f.Type, length)) + } + return bufferLen + case *arrow.SparseUnionType: + // type codes + bufferLen = maxOf(length) + // creates children of the same length of the union + for _, f := range dt.Fields() { + bufferLen = maxOf(getMaxBufferLen(f.Type, length)) + } + return bufferLen + case *arrow.DenseUnionType: + // type codes + bufferLen = maxOf(length) + // offsets + bufferLen = maxOf(arrow.Int32SizeBytes * length) + // create children of length 1 + for _, f := range dt.Fields() { + bufferLen = maxOf(getMaxBufferLen(f.Type, 1)) + } + return bufferLen + case arrow.OffsetsDataType: + return maxOf(dt.OffsetTypeTraits().BytesRequired(length + 1)) + case *arrow.FixedSizeListType: + return maxOf(getMaxBufferLen(dt.Elem(), int(dt.Len())*length)) + case arrow.ExtensionType: + return maxOf(getMaxBufferLen(dt.StorageType(), length)) + default: + panic(fmt.Errorf("arrow/array: arrayofnull not implemented for type %s", dt)) + } +} + +type nullArrayFactory struct { + mem memory.Allocator + dt arrow.DataType + len int + buf *memory.Buffer +} + +func (n *nullArrayFactory) create() *Data { + if n.buf == nil { + bufLen := getMaxBufferLen(n.dt, n.len) + n.buf = memory.NewResizableBuffer(n.mem) + n.buf.Resize(bufLen) + defer n.buf.Release() + } + + var ( + dt = n.dt + bufs = []*memory.Buffer{memory.SliceBuffer(n.buf, 0, int(bitutil.BytesForBits(int64(n.len))))} + childData []arrow.ArrayData + dictData arrow.ArrayData + ) + defer bufs[0].Release() + + if ex, ok := dt.(arrow.ExtensionType); ok { + dt = ex.StorageType() + } + + if nf, ok := dt.(arrow.NestedType); ok { + childData = make([]arrow.ArrayData, len(nf.Fields())) + } + + switch dt := dt.(type) { + case *arrow.NullType: + case *arrow.DictionaryType: + bufs = append(bufs, n.buf) + arr := MakeArrayOfNull(n.mem, dt.ValueType, 0) + defer arr.Release() + dictData = arr.Data() + case arrow.FixedWidthDataType: + bufs = append(bufs, n.buf) + case arrow.BinaryDataType: + bufs = append(bufs, n.buf, n.buf) + case arrow.OffsetsDataType: + bufs = append(bufs, n.buf) + childData[0] = n.createChild(dt, 0, 0) + defer childData[0].Release() + case *arrow.FixedSizeListType: + childData[0] = n.createChild(dt, 0, n.len*int(dt.Len())) + defer childData[0].Release() + case *arrow.StructType: + for i := range dt.Fields() { + childData[i] = n.createChild(dt, i, n.len) + defer childData[i].Release() + } + case *arrow.RunEndEncodedType: + bldr := NewBuilder(n.mem, dt.RunEnds()) + defer bldr.Release() + + switch b := bldr.(type) { + case *Int16Builder: + b.Append(int16(n.len)) + case *Int32Builder: + b.Append(int32(n.len)) + case *Int64Builder: + b.Append(int64(n.len)) + } + + childData[0] = bldr.newData() + defer childData[0].Release() + childData[1] = n.createChild(dt.Encoded(), 1, 1) + defer childData[1].Release() + case arrow.UnionType: + bufs[0].Release() + bufs[0] = nil + bufs = append(bufs, n.buf) + // buffer is zeroed, but 0 may not be a valid type code + if dt.TypeCodes()[0] != 0 { + bufs[1] = memory.NewResizableBuffer(n.mem) + bufs[1].Resize(n.len) + defer bufs[1].Release() + memory.Set(bufs[1].Bytes(), byte(dt.TypeCodes()[0])) + } + + // for sparse unions we create children with the same length + childLen := n.len + if dt.Mode() == arrow.DenseMode { + // for dense unions, offsets are all 0 and make children + // with length 1 + bufs = append(bufs, n.buf) + childLen = 1 + } + for i := range dt.Fields() { + childData[i] = n.createChild(dt, i, childLen) + defer childData[i].Release() + } + } + + out := NewData(n.dt, n.len, bufs, childData, n.len, 0) + if dictData != nil { + out.SetDictionary(dictData) + } + return out +} + +func (n *nullArrayFactory) createChild(dt arrow.DataType, i, length int) *Data { + childFactory := &nullArrayFactory{ + mem: n.mem, dt: n.dt.(arrow.NestedType).Fields()[i].Type, + len: length, buf: n.buf} + return childFactory.create() +} + +// MakeArrayOfNull creates an array of size length which is all null of the given data type. +func MakeArrayOfNull(mem memory.Allocator, dt arrow.DataType, length int) arrow.Array { + if dt.ID() == arrow.NULL { + return NewNull(length) + } + + data := (&nullArrayFactory{mem: mem, dt: dt, len: length}).create() + defer data.Release() + return MakeFromData(data) +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/arrio/arrio.go b/vendor/github.com/apache/arrow/go/v14/arrow/arrio/arrio.go new file mode 100644 index 000000000..466a93a68 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/arrio/arrio.go @@ -0,0 +1,92 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package arrio exposes functions to manipulate records, exposing and using +// interfaces not unlike the ones defined in the stdlib io package. +package arrio + +import ( + "errors" + "io" + + "github.com/apache/arrow/go/v14/arrow" +) + +// Reader is the interface that wraps the Read method. +type Reader interface { + // Read reads the current record from the underlying stream and an error, if any. + // When the Reader reaches the end of the underlying stream, it returns (nil, io.EOF). + Read() (arrow.Record, error) +} + +// ReaderAt is the interface that wraps the ReadAt method. +type ReaderAt interface { + // ReadAt reads the i-th record from the underlying stream and an error, if any. + ReadAt(i int64) (arrow.Record, error) +} + +// Writer is the interface that wraps the Write method. +type Writer interface { + Write(rec arrow.Record) error +} + +// Copy copies all the records available from src to dst. +// Copy returns the number of records copied and the first error +// encountered while copying, if any. +// +// A successful Copy returns err == nil, not err == EOF. Because Copy is +// defined to read from src until EOF, it does not treat an EOF from Read as an +// error to be reported. +func Copy(dst Writer, src Reader) (n int64, err error) { + for { + rec, err := src.Read() + if err != nil { + if errors.Is(err, io.EOF) { + return n, nil + } + return n, err + } + err = dst.Write(rec) + if err != nil { + return n, err + } + n++ + } +} + +// CopyN copies n records (or until an error) from src to dst. It returns the +// number of records copied and the earliest error encountered while copying. On +// return, written == n if and only if err == nil. +func CopyN(dst Writer, src Reader, n int64) (written int64, err error) { + for ; written < n; written++ { + rec, err := src.Read() + if err != nil { + if errors.Is(err, io.EOF) && written == n { + return written, nil + } + return written, err + } + err = dst.Write(rec) + if err != nil { + return written, err + } + } + + if written != n && err == nil { + err = io.EOF + } + return written, err +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/Makefile b/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/Makefile new file mode 100644 index 000000000..12dd1d349 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/Makefile @@ -0,0 +1,62 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# this converts rotate instructions from "ro[lr] " -> "ro[lr] , 1" for yasm compatibility +PERL_FIXUP_ROTATE=perl -i -pe 's/(ro[rl]\s+\w{2,3})$$/\1, 1/' + +C2GOASM=c2goasm +CC=clang-11 +C_FLAGS=-target x86_64-unknown-none -masm=intel -mno-red-zone -mstackrealign -mllvm -inline-threshold=1000 \ + -fno-asynchronous-unwind-tables -fno-exceptions -fno-rtti -O3 -fno-builtin -ffast-math -fno-jump-tables -I_lib +ASM_FLAGS_AVX2=-mavx2 -mfma +ASM_FLAGS_SSE4=-msse4 +ASM_FLAGS_BMI2=-mbmi2 +ASM_FLAGS_POPCNT=-mpopcnt + +C_FLAGS_NEON=-O3 -fvectorize -mllvm -force-vector-width=16 -fno-asynchronous-unwind-tables -mno-red-zone -mstackrealign -fno-exceptions \ + -fno-rtti -fno-builtin -ffast-math -fno-jump-tables -I_lib + +GO_SOURCES := $(shell find . -path ./_lib -prune -o -name '*.go' -not -name '*_test.go') +ALL_SOURCES := $(shell find . -path ./_lib -prune -o -name '*.go' -name '*.s' -not -name '*_test.go') + +.PHONEY: assembly + +INTEL_SOURCES := \ + bitmap_ops_avx2_amd64.s bitmap_ops_sse4_amd64.s + +# +# ARROW-15336: DO NOT add the assembly target for Arm64 (ARM_SOURCES) until c2goasm added the Arm64 support. +# min_max_neon_arm64.s was generated by asm2plan9s. +# And manually formatted it as the Arm64 Plan9. +# + +assembly: $(INTEL_SOURCES) + +_lib/bitmap_ops_avx2_amd64.s: _lib/bitmap_ops.c + $(CC) -S $(C_FLAGS) $(ASM_FLAGS_AVX2) $^ -o $@ ; $(PERL_FIXUP_ROTATE) $@ + +_lib/bitmap_ops_sse4_amd64.s: _lib/bitmap_ops.c + $(CC) -S $(C_FLAGS) $(ASM_FLAGS_SSE4) $^ -o $@ ; $(PERL_FIXUP_ROTATE) $@ + +bitmap_ops_avx2_amd64.s: _lib/bitmap_ops_avx2_amd64.s + $(C2GOASM) -a -f $^ $@ + +bitmap_ops_sse4_amd64.s: _lib/bitmap_ops_sse4_amd64.s + $(C2GOASM) -a -f $^ $@ + +clean: + rm -f $(INTEL_SOURCES) + rm -f $(addprefix _lib/,$(INTEL_SOURCES)) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmap_ops.go b/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmap_ops.go new file mode 100644 index 000000000..7db750a6d --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmap_ops.go @@ -0,0 +1,109 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package bitutil + +func alignedBitAndGo(left, right, out []byte) { + var ( + nbytes = len(out) + i = 0 + ) + if nbytes > uint64SizeBytes { + // case where we have enough bytes to operate on words + leftWords := bytesToUint64(left[i:]) + rightWords := bytesToUint64(right[i:]) + outWords := bytesToUint64(out[i:]) + + for w := range outWords { + outWords[w] = leftWords[w] & rightWords[w] + } + + i += len(outWords) * uint64SizeBytes + } + // grab any remaining bytes that were fewer than a word + for ; i < nbytes; i++ { + out[i] = left[i] & right[i] + } +} + +func alignedBitAndNotGo(left, right, out []byte) { + var ( + nbytes = len(out) + i = 0 + ) + if nbytes > uint64SizeBytes { + // case where we have enough bytes to operate on words + leftWords := bytesToUint64(left[i:]) + rightWords := bytesToUint64(right[i:]) + outWords := bytesToUint64(out[i:]) + + for w := range outWords { + outWords[w] = leftWords[w] &^ rightWords[w] + } + + i += len(outWords) * uint64SizeBytes + } + // grab any remaining bytes that were fewer than a word + for ; i < nbytes; i++ { + out[i] = left[i] &^ right[i] + } +} + +func alignedBitOrGo(left, right, out []byte) { + var ( + nbytes = len(out) + i = 0 + ) + if nbytes > uint64SizeBytes { + // case where we have enough bytes to operate on words + leftWords := bytesToUint64(left[i:]) + rightWords := bytesToUint64(right[i:]) + outWords := bytesToUint64(out[i:]) + + for w := range outWords { + outWords[w] = leftWords[w] | rightWords[w] + } + + i += len(outWords) * uint64SizeBytes + } + // grab any remaining bytes that were fewer than a word + for ; i < nbytes; i++ { + out[i] = left[i] | right[i] + } +} + +func alignedBitXorGo(left, right, out []byte) { + var ( + nbytes = len(out) + i = 0 + ) + if nbytes > uint64SizeBytes { + // case where we have enough bytes to operate on words + leftWords := bytesToUint64(left[i:]) + rightWords := bytesToUint64(right[i:]) + outWords := bytesToUint64(out[i:]) + + for w := range outWords { + outWords[w] = leftWords[w] ^ rightWords[w] + } + + i += len(outWords) * uint64SizeBytes + } + // grab any remaining bytes that were fewer than a word + for ; i < nbytes; i++ { + out[i] = left[i] ^ right[i] + } +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmap_ops_amd64.go b/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmap_ops_amd64.go new file mode 100644 index 000000000..ad0fd674a --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmap_ops_amd64.go @@ -0,0 +1,41 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !noasm +// +build !noasm + +package bitutil + +import "golang.org/x/sys/cpu" + +func init() { + if cpu.X86.HasAVX2 { + bitAndOp.opAligned = bitmapAlignedAndAVX2 + bitOrOp.opAligned = bitmapAlignedOrAVX2 + bitAndNotOp.opAligned = bitmapAlignedAndNotAVX2 + bitXorOp.opAligned = bitmapAlignedXorAVX2 + } else if cpu.X86.HasSSE42 { + bitAndOp.opAligned = bitmapAlignedAndSSE4 + bitOrOp.opAligned = bitmapAlignedOrSSE4 + bitAndNotOp.opAligned = bitmapAlignedAndNotSSE4 + bitXorOp.opAligned = bitmapAlignedXorSSE4 + } else { + bitAndOp.opAligned = alignedBitAndGo + bitOrOp.opAligned = alignedBitOrGo + bitAndNotOp.opAligned = alignedBitAndNotGo + bitXorOp.opAligned = alignedBitXorGo + } +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmap_ops_arm64.go b/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmap_ops_arm64.go new file mode 100644 index 000000000..28d95d84a --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmap_ops_arm64.go @@ -0,0 +1,27 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !noasm +// +build !noasm + +package bitutil + +func init() { + bitAndOp.opAligned = alignedBitAndGo + bitOrOp.opAligned = alignedBitOrGo + bitAndNotOp.opAligned = alignedBitAndNotGo + bitXorOp.opAligned = alignedBitXorGo +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmap_ops_avx2_amd64.go b/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmap_ops_avx2_amd64.go new file mode 100644 index 000000000..1c01bd0f3 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmap_ops_avx2_amd64.go @@ -0,0 +1,52 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !noasm +// +build !noasm + +package bitutil + +import ( + "unsafe" +) + +//go:noescape +func _bitmap_aligned_and_avx2(left, right, out unsafe.Pointer, length int64) + +func bitmapAlignedAndAVX2(left, right, out []byte) { + _bitmap_aligned_and_avx2(unsafe.Pointer(&left[0]), unsafe.Pointer(&right[0]), unsafe.Pointer(&out[0]), int64(len(out))) +} + +//go:noescape +func _bitmap_aligned_or_avx2(left, right, out unsafe.Pointer, length int64) + +func bitmapAlignedOrAVX2(left, right, out []byte) { + _bitmap_aligned_or_avx2(unsafe.Pointer(&left[0]), unsafe.Pointer(&right[0]), unsafe.Pointer(&out[0]), int64(len(out))) +} + +//go:noescape +func _bitmap_aligned_and_not_avx2(left, right, out unsafe.Pointer, length int64) + +func bitmapAlignedAndNotAVX2(left, right, out []byte) { + _bitmap_aligned_and_not_avx2(unsafe.Pointer(&left[0]), unsafe.Pointer(&right[0]), unsafe.Pointer(&out[0]), int64(len(out))) +} + +//go:noescape +func _bitmap_aligned_xor_avx2(left, right, out unsafe.Pointer, length int64) + +func bitmapAlignedXorAVX2(left, right, out []byte) { + _bitmap_aligned_xor_avx2(unsafe.Pointer(&left[0]), unsafe.Pointer(&right[0]), unsafe.Pointer(&out[0]), int64(len(out))) +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmap_ops_avx2_amd64.s b/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmap_ops_avx2_amd64.s new file mode 100644 index 000000000..00172e865 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmap_ops_avx2_amd64.s @@ -0,0 +1,373 @@ +//+build !noasm !appengine +// AUTO-GENERATED BY C2GOASM -- DO NOT EDIT + +TEXT ·_bitmap_aligned_and_avx2(SB), $0-32 + + MOVQ left+0(FP), DI + MOVQ right+8(FP), SI + MOVQ out+16(FP), DX + MOVQ length+24(FP), CX + + WORD $0x8548; BYTE $0xc9 // test rcx, rcx + JLE LBB0_12 + LONG $0x7ff98348 // cmp rcx, 127 + JA LBB0_7 + WORD $0x3145; BYTE $0xd2 // xor r10d, r10d + JMP LBB0_3 + +LBB0_7: + LONG $0x0a0c8d4c // lea r9, [rdx + rcx] + LONG $0x0f048d48 // lea rax, [rdi + rcx] + WORD $0x3948; BYTE $0xd0 // cmp rax, rdx + LONG $0xd3970f41 // seta r11b + LONG $0x0e048d48 // lea rax, [rsi + rcx] + WORD $0x3949; BYTE $0xf9 // cmp r9, rdi + WORD $0x970f; BYTE $0xd3 // seta bl + WORD $0x3948; BYTE $0xd0 // cmp rax, rdx + LONG $0xd0970f41 // seta r8b + WORD $0x3949; BYTE $0xf1 // cmp r9, rsi + LONG $0xd1970f41 // seta r9b + WORD $0x3145; BYTE $0xd2 // xor r10d, r10d + WORD $0x8441; BYTE $0xdb // test r11b, bl + JNE LBB0_3 + WORD $0x2045; BYTE $0xc8 // and r8b, r9b + JNE LBB0_3 + WORD $0x8949; BYTE $0xca // mov r10, rcx + LONG $0x80e28349 // and r10, -128 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB0_10: + LONG $0x107ca1c4; WORD $0x0604 // vmovups ymm0, yword [rsi + r8] + LONG $0x107ca1c4; WORD $0x064c; BYTE $0x20 // vmovups ymm1, yword [rsi + r8 + 32] + LONG $0x107ca1c4; WORD $0x0654; BYTE $0x40 // vmovups ymm2, yword [rsi + r8 + 64] + LONG $0x107ca1c4; WORD $0x065c; BYTE $0x60 // vmovups ymm3, yword [rsi + r8 + 96] + LONG $0x547ca1c4; WORD $0x0704 // vandps ymm0, ymm0, yword [rdi + r8] + LONG $0x5474a1c4; WORD $0x074c; BYTE $0x20 // vandps ymm1, ymm1, yword [rdi + r8 + 32] + LONG $0x546ca1c4; WORD $0x0754; BYTE $0x40 // vandps ymm2, ymm2, yword [rdi + r8 + 64] + LONG $0x5464a1c4; WORD $0x075c; BYTE $0x60 // vandps ymm3, ymm3, yword [rdi + r8 + 96] + LONG $0x117ca1c4; WORD $0x0204 // vmovups yword [rdx + r8], ymm0 + LONG $0x117ca1c4; WORD $0x024c; BYTE $0x20 // vmovups yword [rdx + r8 + 32], ymm1 + LONG $0x117ca1c4; WORD $0x0254; BYTE $0x40 // vmovups yword [rdx + r8 + 64], ymm2 + LONG $0x117ca1c4; WORD $0x025c; BYTE $0x60 // vmovups yword [rdx + r8 + 96], ymm3 + LONG $0x80e88349 // sub r8, -128 + WORD $0x394d; BYTE $0xc2 // cmp r10, r8 + JNE LBB0_10 + WORD $0x3949; BYTE $0xca // cmp r10, rcx + JE LBB0_12 + +LBB0_3: + WORD $0x894d; BYTE $0xd0 // mov r8, r10 + WORD $0xf749; BYTE $0xd0 // not r8 + WORD $0x0149; BYTE $0xc8 // add r8, rcx + WORD $0x8949; BYTE $0xc9 // mov r9, rcx + LONG $0x03e18349 // and r9, 3 + JE LBB0_5 + +LBB0_4: + LONG $0x04b60f42; BYTE $0x16 // movzx eax, byte [rsi + r10] + LONG $0x17042242 // and al, byte [rdi + r10] + LONG $0x12048842 // mov byte [rdx + r10], al + LONG $0x01c28349 // add r10, 1 + LONG $0xffc18349 // add r9, -1 + JNE LBB0_4 + +LBB0_5: + LONG $0x03f88349 // cmp r8, 3 + JB LBB0_12 + +LBB0_6: + LONG $0x04b60f42; BYTE $0x16 // movzx eax, byte [rsi + r10] + LONG $0x17042242 // and al, byte [rdi + r10] + LONG $0x12048842 // mov byte [rdx + r10], al + LONG $0x44b60f42; WORD $0x0116 // movzx eax, byte [rsi + r10 + 1] + LONG $0x17442242; BYTE $0x01 // and al, byte [rdi + r10 + 1] + LONG $0x12448842; BYTE $0x01 // mov byte [rdx + r10 + 1], al + LONG $0x44b60f42; WORD $0x0216 // movzx eax, byte [rsi + r10 + 2] + LONG $0x17442242; BYTE $0x02 // and al, byte [rdi + r10 + 2] + LONG $0x12448842; BYTE $0x02 // mov byte [rdx + r10 + 2], al + LONG $0x44b60f42; WORD $0x0316 // movzx eax, byte [rsi + r10 + 3] + LONG $0x17442242; BYTE $0x03 // and al, byte [rdi + r10 + 3] + LONG $0x12448842; BYTE $0x03 // mov byte [rdx + r10 + 3], al + LONG $0x04c28349 // add r10, 4 + WORD $0x394c; BYTE $0xd1 // cmp rcx, r10 + JNE LBB0_6 + +LBB0_12: + VZEROUPPER + RET + +TEXT ·_bitmap_aligned_or_avx2(SB), $0-32 + + MOVQ left+0(FP), DI + MOVQ right+8(FP), SI + MOVQ out+16(FP), DX + MOVQ length+24(FP), CX + + WORD $0x8548; BYTE $0xc9 // test rcx, rcx + JLE LBB1_12 + LONG $0x7ff98348 // cmp rcx, 127 + JA LBB1_7 + WORD $0x3145; BYTE $0xd2 // xor r10d, r10d + JMP LBB1_3 + +LBB1_7: + LONG $0x0a0c8d4c // lea r9, [rdx + rcx] + LONG $0x0f048d48 // lea rax, [rdi + rcx] + WORD $0x3948; BYTE $0xd0 // cmp rax, rdx + LONG $0xd3970f41 // seta r11b + LONG $0x0e048d48 // lea rax, [rsi + rcx] + WORD $0x3949; BYTE $0xf9 // cmp r9, rdi + WORD $0x970f; BYTE $0xd3 // seta bl + WORD $0x3948; BYTE $0xd0 // cmp rax, rdx + LONG $0xd0970f41 // seta r8b + WORD $0x3949; BYTE $0xf1 // cmp r9, rsi + LONG $0xd1970f41 // seta r9b + WORD $0x3145; BYTE $0xd2 // xor r10d, r10d + WORD $0x8441; BYTE $0xdb // test r11b, bl + JNE LBB1_3 + WORD $0x2045; BYTE $0xc8 // and r8b, r9b + JNE LBB1_3 + WORD $0x8949; BYTE $0xca // mov r10, rcx + LONG $0x80e28349 // and r10, -128 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB1_10: + LONG $0x107ca1c4; WORD $0x0604 // vmovups ymm0, yword [rsi + r8] + LONG $0x107ca1c4; WORD $0x064c; BYTE $0x20 // vmovups ymm1, yword [rsi + r8 + 32] + LONG $0x107ca1c4; WORD $0x0654; BYTE $0x40 // vmovups ymm2, yword [rsi + r8 + 64] + LONG $0x107ca1c4; WORD $0x065c; BYTE $0x60 // vmovups ymm3, yword [rsi + r8 + 96] + LONG $0x567ca1c4; WORD $0x0704 // vorps ymm0, ymm0, yword [rdi + r8] + LONG $0x5674a1c4; WORD $0x074c; BYTE $0x20 // vorps ymm1, ymm1, yword [rdi + r8 + 32] + LONG $0x566ca1c4; WORD $0x0754; BYTE $0x40 // vorps ymm2, ymm2, yword [rdi + r8 + 64] + LONG $0x5664a1c4; WORD $0x075c; BYTE $0x60 // vorps ymm3, ymm3, yword [rdi + r8 + 96] + LONG $0x117ca1c4; WORD $0x0204 // vmovups yword [rdx + r8], ymm0 + LONG $0x117ca1c4; WORD $0x024c; BYTE $0x20 // vmovups yword [rdx + r8 + 32], ymm1 + LONG $0x117ca1c4; WORD $0x0254; BYTE $0x40 // vmovups yword [rdx + r8 + 64], ymm2 + LONG $0x117ca1c4; WORD $0x025c; BYTE $0x60 // vmovups yword [rdx + r8 + 96], ymm3 + LONG $0x80e88349 // sub r8, -128 + WORD $0x394d; BYTE $0xc2 // cmp r10, r8 + JNE LBB1_10 + WORD $0x3949; BYTE $0xca // cmp r10, rcx + JE LBB1_12 + +LBB1_3: + WORD $0x894d; BYTE $0xd0 // mov r8, r10 + WORD $0xf749; BYTE $0xd0 // not r8 + WORD $0x0149; BYTE $0xc8 // add r8, rcx + WORD $0x8949; BYTE $0xc9 // mov r9, rcx + LONG $0x03e18349 // and r9, 3 + JE LBB1_5 + +LBB1_4: + LONG $0x04b60f42; BYTE $0x16 // movzx eax, byte [rsi + r10] + LONG $0x17040a42 // or al, byte [rdi + r10] + LONG $0x12048842 // mov byte [rdx + r10], al + LONG $0x01c28349 // add r10, 1 + LONG $0xffc18349 // add r9, -1 + JNE LBB1_4 + +LBB1_5: + LONG $0x03f88349 // cmp r8, 3 + JB LBB1_12 + +LBB1_6: + LONG $0x04b60f42; BYTE $0x16 // movzx eax, byte [rsi + r10] + LONG $0x17040a42 // or al, byte [rdi + r10] + LONG $0x12048842 // mov byte [rdx + r10], al + LONG $0x44b60f42; WORD $0x0116 // movzx eax, byte [rsi + r10 + 1] + LONG $0x17440a42; BYTE $0x01 // or al, byte [rdi + r10 + 1] + LONG $0x12448842; BYTE $0x01 // mov byte [rdx + r10 + 1], al + LONG $0x44b60f42; WORD $0x0216 // movzx eax, byte [rsi + r10 + 2] + LONG $0x17440a42; BYTE $0x02 // or al, byte [rdi + r10 + 2] + LONG $0x12448842; BYTE $0x02 // mov byte [rdx + r10 + 2], al + LONG $0x44b60f42; WORD $0x0316 // movzx eax, byte [rsi + r10 + 3] + LONG $0x17440a42; BYTE $0x03 // or al, byte [rdi + r10 + 3] + LONG $0x12448842; BYTE $0x03 // mov byte [rdx + r10 + 3], al + LONG $0x04c28349 // add r10, 4 + WORD $0x394c; BYTE $0xd1 // cmp rcx, r10 + JNE LBB1_6 + +LBB1_12: + VZEROUPPER + RET + +TEXT ·_bitmap_aligned_and_not_avx2(SB), $0-32 + + MOVQ left+0(FP), DI + MOVQ right+8(FP), SI + MOVQ out+16(FP), DX + MOVQ length+24(FP), CX + + WORD $0x8548; BYTE $0xc9 // test rcx, rcx + JLE LBB2_12 + LONG $0x7ff98348 // cmp rcx, 127 + JA LBB2_7 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + JMP LBB2_3 + +LBB2_7: + LONG $0x0a048d4c // lea r8, [rdx + rcx] + LONG $0x0f048d48 // lea rax, [rdi + rcx] + WORD $0x3948; BYTE $0xd0 // cmp rax, rdx + LONG $0xd3970f41 // seta r11b + LONG $0x0e048d48 // lea rax, [rsi + rcx] + WORD $0x3949; BYTE $0xf8 // cmp r8, rdi + WORD $0x970f; BYTE $0xd3 // seta bl + WORD $0x3948; BYTE $0xd0 // cmp rax, rdx + LONG $0xd2970f41 // seta r10b + WORD $0x3949; BYTE $0xf0 // cmp r8, rsi + LONG $0xd1970f41 // seta r9b + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + WORD $0x8441; BYTE $0xdb // test r11b, bl + JNE LBB2_3 + WORD $0x2045; BYTE $0xca // and r10b, r9b + JNE LBB2_3 + WORD $0x8949; BYTE $0xc8 // mov r8, rcx + LONG $0x80e08349 // and r8, -128 + WORD $0xc031 // xor eax, eax + +LBB2_10: + LONG $0x0410fcc5; BYTE $0x06 // vmovups ymm0, yword [rsi + rax] + LONG $0x4c10fcc5; WORD $0x2006 // vmovups ymm1, yword [rsi + rax + 32] + LONG $0x5410fcc5; WORD $0x4006 // vmovups ymm2, yword [rsi + rax + 64] + LONG $0x5c10fcc5; WORD $0x6006 // vmovups ymm3, yword [rsi + rax + 96] + LONG $0x0455fcc5; BYTE $0x07 // vandnps ymm0, ymm0, yword [rdi + rax] + LONG $0x4c55f4c5; WORD $0x2007 // vandnps ymm1, ymm1, yword [rdi + rax + 32] + LONG $0x5455ecc5; WORD $0x4007 // vandnps ymm2, ymm2, yword [rdi + rax + 64] + LONG $0x5c55e4c5; WORD $0x6007 // vandnps ymm3, ymm3, yword [rdi + rax + 96] + LONG $0x0411fcc5; BYTE $0x02 // vmovups yword [rdx + rax], ymm0 + LONG $0x4c11fcc5; WORD $0x2002 // vmovups yword [rdx + rax + 32], ymm1 + LONG $0x5411fcc5; WORD $0x4002 // vmovups yword [rdx + rax + 64], ymm2 + LONG $0x5c11fcc5; WORD $0x6002 // vmovups yword [rdx + rax + 96], ymm3 + LONG $0x80e88348 // sub rax, -128 + WORD $0x3949; BYTE $0xc0 // cmp r8, rax + JNE LBB2_10 + WORD $0x3949; BYTE $0xc8 // cmp r8, rcx + JE LBB2_12 + +LBB2_3: + WORD $0x894d; BYTE $0xc1 // mov r9, r8 + WORD $0xf749; BYTE $0xd1 // not r9 + WORD $0xc1f6; BYTE $0x01 // test cl, 1 + JE LBB2_5 + LONG $0x06048a42 // mov al, byte [rsi + r8] + WORD $0xd0f6 // not al + LONG $0x07042242 // and al, byte [rdi + r8] + LONG $0x02048842 // mov byte [rdx + r8], al + LONG $0x01c88349 // or r8, 1 + +LBB2_5: + WORD $0x0149; BYTE $0xc9 // add r9, rcx + JE LBB2_12 + +LBB2_6: + LONG $0x04b60f42; BYTE $0x06 // movzx eax, byte [rsi + r8] + WORD $0xd0f6 // not al + LONG $0x07042242 // and al, byte [rdi + r8] + LONG $0x02048842 // mov byte [rdx + r8], al + LONG $0x44b60f42; WORD $0x0106 // movzx eax, byte [rsi + r8 + 1] + WORD $0xd0f6 // not al + LONG $0x07442242; BYTE $0x01 // and al, byte [rdi + r8 + 1] + LONG $0x02448842; BYTE $0x01 // mov byte [rdx + r8 + 1], al + LONG $0x02c08349 // add r8, 2 + WORD $0x394c; BYTE $0xc1 // cmp rcx, r8 + JNE LBB2_6 + +LBB2_12: + VZEROUPPER + RET + +TEXT ·_bitmap_aligned_xor_avx2(SB), $0-32 + + MOVQ left+0(FP), DI + MOVQ right+8(FP), SI + MOVQ out+16(FP), DX + MOVQ length+24(FP), CX + + WORD $0x8548; BYTE $0xc9 // test rcx, rcx + JLE LBB3_12 + LONG $0x7ff98348 // cmp rcx, 127 + JA LBB3_7 + WORD $0x3145; BYTE $0xd2 // xor r10d, r10d + JMP LBB3_3 + +LBB3_7: + LONG $0x0a0c8d4c // lea r9, [rdx + rcx] + LONG $0x0f048d48 // lea rax, [rdi + rcx] + WORD $0x3948; BYTE $0xd0 // cmp rax, rdx + LONG $0xd3970f41 // seta r11b + LONG $0x0e048d48 // lea rax, [rsi + rcx] + WORD $0x3949; BYTE $0xf9 // cmp r9, rdi + WORD $0x970f; BYTE $0xd3 // seta bl + WORD $0x3948; BYTE $0xd0 // cmp rax, rdx + LONG $0xd0970f41 // seta r8b + WORD $0x3949; BYTE $0xf1 // cmp r9, rsi + LONG $0xd1970f41 // seta r9b + WORD $0x3145; BYTE $0xd2 // xor r10d, r10d + WORD $0x8441; BYTE $0xdb // test r11b, bl + JNE LBB3_3 + WORD $0x2045; BYTE $0xc8 // and r8b, r9b + JNE LBB3_3 + WORD $0x8949; BYTE $0xca // mov r10, rcx + LONG $0x80e28349 // and r10, -128 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB3_10: + LONG $0x107ca1c4; WORD $0x0604 // vmovups ymm0, yword [rsi + r8] + LONG $0x107ca1c4; WORD $0x064c; BYTE $0x20 // vmovups ymm1, yword [rsi + r8 + 32] + LONG $0x107ca1c4; WORD $0x0654; BYTE $0x40 // vmovups ymm2, yword [rsi + r8 + 64] + LONG $0x107ca1c4; WORD $0x065c; BYTE $0x60 // vmovups ymm3, yword [rsi + r8 + 96] + LONG $0x577ca1c4; WORD $0x0704 // vxorps ymm0, ymm0, yword [rdi + r8] + LONG $0x5774a1c4; WORD $0x074c; BYTE $0x20 // vxorps ymm1, ymm1, yword [rdi + r8 + 32] + LONG $0x576ca1c4; WORD $0x0754; BYTE $0x40 // vxorps ymm2, ymm2, yword [rdi + r8 + 64] + LONG $0x5764a1c4; WORD $0x075c; BYTE $0x60 // vxorps ymm3, ymm3, yword [rdi + r8 + 96] + LONG $0x117ca1c4; WORD $0x0204 // vmovups yword [rdx + r8], ymm0 + LONG $0x117ca1c4; WORD $0x024c; BYTE $0x20 // vmovups yword [rdx + r8 + 32], ymm1 + LONG $0x117ca1c4; WORD $0x0254; BYTE $0x40 // vmovups yword [rdx + r8 + 64], ymm2 + LONG $0x117ca1c4; WORD $0x025c; BYTE $0x60 // vmovups yword [rdx + r8 + 96], ymm3 + LONG $0x80e88349 // sub r8, -128 + WORD $0x394d; BYTE $0xc2 // cmp r10, r8 + JNE LBB3_10 + WORD $0x3949; BYTE $0xca // cmp r10, rcx + JE LBB3_12 + +LBB3_3: + WORD $0x894d; BYTE $0xd0 // mov r8, r10 + WORD $0xf749; BYTE $0xd0 // not r8 + WORD $0x0149; BYTE $0xc8 // add r8, rcx + WORD $0x8949; BYTE $0xc9 // mov r9, rcx + LONG $0x03e18349 // and r9, 3 + JE LBB3_5 + +LBB3_4: + LONG $0x04b60f42; BYTE $0x16 // movzx eax, byte [rsi + r10] + LONG $0x17043242 // xor al, byte [rdi + r10] + LONG $0x12048842 // mov byte [rdx + r10], al + LONG $0x01c28349 // add r10, 1 + LONG $0xffc18349 // add r9, -1 + JNE LBB3_4 + +LBB3_5: + LONG $0x03f88349 // cmp r8, 3 + JB LBB3_12 + +LBB3_6: + LONG $0x04b60f42; BYTE $0x16 // movzx eax, byte [rsi + r10] + LONG $0x17043242 // xor al, byte [rdi + r10] + LONG $0x12048842 // mov byte [rdx + r10], al + LONG $0x44b60f42; WORD $0x0116 // movzx eax, byte [rsi + r10 + 1] + LONG $0x17443242; BYTE $0x01 // xor al, byte [rdi + r10 + 1] + LONG $0x12448842; BYTE $0x01 // mov byte [rdx + r10 + 1], al + LONG $0x44b60f42; WORD $0x0216 // movzx eax, byte [rsi + r10 + 2] + LONG $0x17443242; BYTE $0x02 // xor al, byte [rdi + r10 + 2] + LONG $0x12448842; BYTE $0x02 // mov byte [rdx + r10 + 2], al + LONG $0x44b60f42; WORD $0x0316 // movzx eax, byte [rsi + r10 + 3] + LONG $0x17443242; BYTE $0x03 // xor al, byte [rdi + r10 + 3] + LONG $0x12448842; BYTE $0x03 // mov byte [rdx + r10 + 3], al + LONG $0x04c28349 // add r10, 4 + WORD $0x394c; BYTE $0xd1 // cmp rcx, r10 + JNE LBB3_6 + +LBB3_12: + VZEROUPPER + RET diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmap_ops_noasm.go b/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmap_ops_noasm.go new file mode 100644 index 000000000..e25347791 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmap_ops_noasm.go @@ -0,0 +1,27 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build noasm +// +build noasm + +package bitutil + +func init() { + bitAndOp.opAligned = alignedBitAndGo + bitOrOp.opAligned = alignedBitOrGo + bitAndNotOp.opAligned = alignedBitAndNotGo + bitXorOp.opAligned = alignedBitXorGo +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmap_ops_ppc64le.go b/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmap_ops_ppc64le.go new file mode 100644 index 000000000..28d95d84a --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmap_ops_ppc64le.go @@ -0,0 +1,27 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !noasm +// +build !noasm + +package bitutil + +func init() { + bitAndOp.opAligned = alignedBitAndGo + bitOrOp.opAligned = alignedBitOrGo + bitAndNotOp.opAligned = alignedBitAndNotGo + bitXorOp.opAligned = alignedBitXorGo +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmap_ops_s390x.go b/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmap_ops_s390x.go new file mode 100644 index 000000000..28d95d84a --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmap_ops_s390x.go @@ -0,0 +1,27 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !noasm +// +build !noasm + +package bitutil + +func init() { + bitAndOp.opAligned = alignedBitAndGo + bitOrOp.opAligned = alignedBitOrGo + bitAndNotOp.opAligned = alignedBitAndNotGo + bitXorOp.opAligned = alignedBitXorGo +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmap_ops_sse4_amd64.go b/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmap_ops_sse4_amd64.go new file mode 100644 index 000000000..f16bce12b --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmap_ops_sse4_amd64.go @@ -0,0 +1,52 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !noasm +// +build !noasm + +package bitutil + +import ( + "unsafe" +) + +//go:noescape +func _bitmap_aligned_and_sse4(left, right, out unsafe.Pointer, length int64) + +func bitmapAlignedAndSSE4(left, right, out []byte) { + _bitmap_aligned_and_sse4(unsafe.Pointer(&left[0]), unsafe.Pointer(&right[0]), unsafe.Pointer(&out[0]), int64(len(out))) +} + +//go:noescape +func _bitmap_aligned_or_sse4(left, right, out unsafe.Pointer, length int64) + +func bitmapAlignedOrSSE4(left, right, out []byte) { + _bitmap_aligned_or_sse4(unsafe.Pointer(&left[0]), unsafe.Pointer(&right[0]), unsafe.Pointer(&out[0]), int64(len(out))) +} + +//go:noescape +func _bitmap_aligned_and_not_sse4(left, right, out unsafe.Pointer, length int64) + +func bitmapAlignedAndNotSSE4(left, right, out []byte) { + _bitmap_aligned_and_not_sse4(unsafe.Pointer(&left[0]), unsafe.Pointer(&right[0]), unsafe.Pointer(&out[0]), int64(len(out))) +} + +//go:noescape +func _bitmap_aligned_xor_sse4(left, right, out unsafe.Pointer, length int64) + +func bitmapAlignedXorSSE4(left, right, out []byte) { + _bitmap_aligned_xor_sse4(unsafe.Pointer(&left[0]), unsafe.Pointer(&right[0]), unsafe.Pointer(&out[0]), int64(len(out))) +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmap_ops_sse4_amd64.s b/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmap_ops_sse4_amd64.s new file mode 100644 index 000000000..c15e18625 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmap_ops_sse4_amd64.s @@ -0,0 +1,501 @@ +//+build !noasm !appengine +// AUTO-GENERATED BY C2GOASM -- DO NOT EDIT + +TEXT ·_bitmap_aligned_and_sse4(SB), $0-32 + + MOVQ left+0(FP), DI + MOVQ right+8(FP), SI + MOVQ out+16(FP), DX + MOVQ length+24(FP), CX + + WORD $0x8548; BYTE $0xc9 // test rcx, rcx + JLE LBB0_16 + LONG $0x1ff98348 // cmp rcx, 31 + JA LBB0_7 + WORD $0x3145; BYTE $0xdb // xor r11d, r11d + +LBB0_3: + WORD $0x894d; BYTE $0xd8 // mov r8, r11 + WORD $0xf749; BYTE $0xd0 // not r8 + WORD $0x0149; BYTE $0xc8 // add r8, rcx + WORD $0x8949; BYTE $0xc9 // mov r9, rcx + LONG $0x03e18349 // and r9, 3 + JE LBB0_5 + +LBB0_4: + LONG $0x04b60f42; BYTE $0x1e // movzx eax, byte [rsi + r11] + LONG $0x1f042242 // and al, byte [rdi + r11] + LONG $0x1a048842 // mov byte [rdx + r11], al + LONG $0x01c38349 // add r11, 1 + LONG $0xffc18349 // add r9, -1 + JNE LBB0_4 + +LBB0_5: + LONG $0x03f88349 // cmp r8, 3 + JB LBB0_16 + +LBB0_6: + LONG $0x04b60f42; BYTE $0x1e // movzx eax, byte [rsi + r11] + LONG $0x1f042242 // and al, byte [rdi + r11] + LONG $0x1a048842 // mov byte [rdx + r11], al + LONG $0x44b60f42; WORD $0x011e // movzx eax, byte [rsi + r11 + 1] + LONG $0x1f442242; BYTE $0x01 // and al, byte [rdi + r11 + 1] + LONG $0x1a448842; BYTE $0x01 // mov byte [rdx + r11 + 1], al + LONG $0x44b60f42; WORD $0x021e // movzx eax, byte [rsi + r11 + 2] + LONG $0x1f442242; BYTE $0x02 // and al, byte [rdi + r11 + 2] + LONG $0x1a448842; BYTE $0x02 // mov byte [rdx + r11 + 2], al + LONG $0x44b60f42; WORD $0x031e // movzx eax, byte [rsi + r11 + 3] + LONG $0x1f442242; BYTE $0x03 // and al, byte [rdi + r11 + 3] + LONG $0x1a448842; BYTE $0x03 // mov byte [rdx + r11 + 3], al + LONG $0x04c38349 // add r11, 4 + WORD $0x394c; BYTE $0xd9 // cmp rcx, r11 + JNE LBB0_6 + JMP LBB0_16 + +LBB0_7: + LONG $0x0a0c8d4c // lea r9, [rdx + rcx] + LONG $0x0f048d48 // lea rax, [rdi + rcx] + WORD $0x3948; BYTE $0xd0 // cmp rax, rdx + LONG $0xd2970f41 // seta r10b + LONG $0x0e048d48 // lea rax, [rsi + rcx] + WORD $0x3949; BYTE $0xf9 // cmp r9, rdi + WORD $0x970f; BYTE $0xd3 // seta bl + WORD $0x3948; BYTE $0xd0 // cmp rax, rdx + LONG $0xd0970f41 // seta r8b + WORD $0x3949; BYTE $0xf1 // cmp r9, rsi + LONG $0xd1970f41 // seta r9b + WORD $0x3145; BYTE $0xdb // xor r11d, r11d + WORD $0x8441; BYTE $0xda // test r10b, bl + JNE LBB0_3 + WORD $0x2045; BYTE $0xc8 // and r8b, r9b + JNE LBB0_3 + WORD $0x8949; BYTE $0xcb // mov r11, rcx + LONG $0xe0e38349 // and r11, -32 + LONG $0xe0438d49 // lea rax, [r11 - 32] + WORD $0x8949; BYTE $0xc1 // mov r9, rax + LONG $0x05e9c149 // shr r9, 5 + LONG $0x01c18349 // add r9, 1 + WORD $0x8548; BYTE $0xc0 // test rax, rax + JE LBB0_10 + WORD $0x894d; BYTE $0xca // mov r10, r9 + LONG $0xfee28349 // and r10, -2 + WORD $0xf749; BYTE $0xda // neg r10 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB0_12: + LONG $0x04100f42; BYTE $0x07 // movups xmm0, oword [rdi + r8] + LONG $0x4c100f42; WORD $0x1007 // movups xmm1, oword [rdi + r8 + 16] + LONG $0x14100f42; BYTE $0x06 // movups xmm2, oword [rsi + r8] + WORD $0x540f; BYTE $0xd0 // andps xmm2, xmm0 + LONG $0x44100f42; WORD $0x1006 // movups xmm0, oword [rsi + r8 + 16] + WORD $0x540f; BYTE $0xc1 // andps xmm0, xmm1 + LONG $0x14110f42; BYTE $0x02 // movups oword [rdx + r8], xmm2 + LONG $0x44110f42; WORD $0x1002 // movups oword [rdx + r8 + 16], xmm0 + LONG $0x44100f42; WORD $0x2007 // movups xmm0, oword [rdi + r8 + 32] + LONG $0x4c100f42; WORD $0x3007 // movups xmm1, oword [rdi + r8 + 48] + LONG $0x54100f42; WORD $0x2006 // movups xmm2, oword [rsi + r8 + 32] + WORD $0x540f; BYTE $0xd0 // andps xmm2, xmm0 + LONG $0x44100f42; WORD $0x3006 // movups xmm0, oword [rsi + r8 + 48] + WORD $0x540f; BYTE $0xc1 // andps xmm0, xmm1 + LONG $0x54110f42; WORD $0x2002 // movups oword [rdx + r8 + 32], xmm2 + LONG $0x44110f42; WORD $0x3002 // movups oword [rdx + r8 + 48], xmm0 + LONG $0x40c08349 // add r8, 64 + LONG $0x02c28349 // add r10, 2 + JNE LBB0_12 + LONG $0x01c1f641 // test r9b, 1 + JE LBB0_15 + +LBB0_14: + LONG $0x04100f42; BYTE $0x07 // movups xmm0, oword [rdi + r8] + LONG $0x4c100f42; WORD $0x1007 // movups xmm1, oword [rdi + r8 + 16] + LONG $0x14100f42; BYTE $0x06 // movups xmm2, oword [rsi + r8] + WORD $0x540f; BYTE $0xd0 // andps xmm2, xmm0 + LONG $0x44100f42; WORD $0x1006 // movups xmm0, oword [rsi + r8 + 16] + WORD $0x540f; BYTE $0xc1 // andps xmm0, xmm1 + LONG $0x14110f42; BYTE $0x02 // movups oword [rdx + r8], xmm2 + LONG $0x44110f42; WORD $0x1002 // movups oword [rdx + r8 + 16], xmm0 + +LBB0_15: + WORD $0x3949; BYTE $0xcb // cmp r11, rcx + JNE LBB0_3 + +LBB0_16: + RET + +LBB0_10: + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + LONG $0x01c1f641 // test r9b, 1 + JNE LBB0_14 + JMP LBB0_15 + +TEXT ·_bitmap_aligned_or_sse4(SB), $0-32 + + MOVQ left+0(FP), DI + MOVQ right+8(FP), SI + MOVQ out+16(FP), DX + MOVQ length+24(FP), CX + + WORD $0x8548; BYTE $0xc9 // test rcx, rcx + JLE LBB1_16 + LONG $0x1ff98348 // cmp rcx, 31 + JA LBB1_7 + WORD $0x3145; BYTE $0xdb // xor r11d, r11d + +LBB1_3: + WORD $0x894d; BYTE $0xd8 // mov r8, r11 + WORD $0xf749; BYTE $0xd0 // not r8 + WORD $0x0149; BYTE $0xc8 // add r8, rcx + WORD $0x8949; BYTE $0xc9 // mov r9, rcx + LONG $0x03e18349 // and r9, 3 + JE LBB1_5 + +LBB1_4: + LONG $0x04b60f42; BYTE $0x1e // movzx eax, byte [rsi + r11] + LONG $0x1f040a42 // or al, byte [rdi + r11] + LONG $0x1a048842 // mov byte [rdx + r11], al + LONG $0x01c38349 // add r11, 1 + LONG $0xffc18349 // add r9, -1 + JNE LBB1_4 + +LBB1_5: + LONG $0x03f88349 // cmp r8, 3 + JB LBB1_16 + +LBB1_6: + LONG $0x04b60f42; BYTE $0x1e // movzx eax, byte [rsi + r11] + LONG $0x1f040a42 // or al, byte [rdi + r11] + LONG $0x1a048842 // mov byte [rdx + r11], al + LONG $0x44b60f42; WORD $0x011e // movzx eax, byte [rsi + r11 + 1] + LONG $0x1f440a42; BYTE $0x01 // or al, byte [rdi + r11 + 1] + LONG $0x1a448842; BYTE $0x01 // mov byte [rdx + r11 + 1], al + LONG $0x44b60f42; WORD $0x021e // movzx eax, byte [rsi + r11 + 2] + LONG $0x1f440a42; BYTE $0x02 // or al, byte [rdi + r11 + 2] + LONG $0x1a448842; BYTE $0x02 // mov byte [rdx + r11 + 2], al + LONG $0x44b60f42; WORD $0x031e // movzx eax, byte [rsi + r11 + 3] + LONG $0x1f440a42; BYTE $0x03 // or al, byte [rdi + r11 + 3] + LONG $0x1a448842; BYTE $0x03 // mov byte [rdx + r11 + 3], al + LONG $0x04c38349 // add r11, 4 + WORD $0x394c; BYTE $0xd9 // cmp rcx, r11 + JNE LBB1_6 + JMP LBB1_16 + +LBB1_7: + LONG $0x0a0c8d4c // lea r9, [rdx + rcx] + LONG $0x0f048d48 // lea rax, [rdi + rcx] + WORD $0x3948; BYTE $0xd0 // cmp rax, rdx + LONG $0xd2970f41 // seta r10b + LONG $0x0e048d48 // lea rax, [rsi + rcx] + WORD $0x3949; BYTE $0xf9 // cmp r9, rdi + WORD $0x970f; BYTE $0xd3 // seta bl + WORD $0x3948; BYTE $0xd0 // cmp rax, rdx + LONG $0xd0970f41 // seta r8b + WORD $0x3949; BYTE $0xf1 // cmp r9, rsi + LONG $0xd1970f41 // seta r9b + WORD $0x3145; BYTE $0xdb // xor r11d, r11d + WORD $0x8441; BYTE $0xda // test r10b, bl + JNE LBB1_3 + WORD $0x2045; BYTE $0xc8 // and r8b, r9b + JNE LBB1_3 + WORD $0x8949; BYTE $0xcb // mov r11, rcx + LONG $0xe0e38349 // and r11, -32 + LONG $0xe0438d49 // lea rax, [r11 - 32] + WORD $0x8949; BYTE $0xc1 // mov r9, rax + LONG $0x05e9c149 // shr r9, 5 + LONG $0x01c18349 // add r9, 1 + WORD $0x8548; BYTE $0xc0 // test rax, rax + JE LBB1_10 + WORD $0x894d; BYTE $0xca // mov r10, r9 + LONG $0xfee28349 // and r10, -2 + WORD $0xf749; BYTE $0xda // neg r10 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB1_12: + LONG $0x04100f42; BYTE $0x07 // movups xmm0, oword [rdi + r8] + LONG $0x4c100f42; WORD $0x1007 // movups xmm1, oword [rdi + r8 + 16] + LONG $0x14100f42; BYTE $0x06 // movups xmm2, oword [rsi + r8] + WORD $0x560f; BYTE $0xd0 // orps xmm2, xmm0 + LONG $0x44100f42; WORD $0x1006 // movups xmm0, oword [rsi + r8 + 16] + WORD $0x560f; BYTE $0xc1 // orps xmm0, xmm1 + LONG $0x14110f42; BYTE $0x02 // movups oword [rdx + r8], xmm2 + LONG $0x44110f42; WORD $0x1002 // movups oword [rdx + r8 + 16], xmm0 + LONG $0x44100f42; WORD $0x2007 // movups xmm0, oword [rdi + r8 + 32] + LONG $0x4c100f42; WORD $0x3007 // movups xmm1, oword [rdi + r8 + 48] + LONG $0x54100f42; WORD $0x2006 // movups xmm2, oword [rsi + r8 + 32] + WORD $0x560f; BYTE $0xd0 // orps xmm2, xmm0 + LONG $0x44100f42; WORD $0x3006 // movups xmm0, oword [rsi + r8 + 48] + WORD $0x560f; BYTE $0xc1 // orps xmm0, xmm1 + LONG $0x54110f42; WORD $0x2002 // movups oword [rdx + r8 + 32], xmm2 + LONG $0x44110f42; WORD $0x3002 // movups oword [rdx + r8 + 48], xmm0 + LONG $0x40c08349 // add r8, 64 + LONG $0x02c28349 // add r10, 2 + JNE LBB1_12 + LONG $0x01c1f641 // test r9b, 1 + JE LBB1_15 + +LBB1_14: + LONG $0x04100f42; BYTE $0x07 // movups xmm0, oword [rdi + r8] + LONG $0x4c100f42; WORD $0x1007 // movups xmm1, oword [rdi + r8 + 16] + LONG $0x14100f42; BYTE $0x06 // movups xmm2, oword [rsi + r8] + WORD $0x560f; BYTE $0xd0 // orps xmm2, xmm0 + LONG $0x44100f42; WORD $0x1006 // movups xmm0, oword [rsi + r8 + 16] + WORD $0x560f; BYTE $0xc1 // orps xmm0, xmm1 + LONG $0x14110f42; BYTE $0x02 // movups oword [rdx + r8], xmm2 + LONG $0x44110f42; WORD $0x1002 // movups oword [rdx + r8 + 16], xmm0 + +LBB1_15: + WORD $0x3949; BYTE $0xcb // cmp r11, rcx + JNE LBB1_3 + +LBB1_16: + RET + +LBB1_10: + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + LONG $0x01c1f641 // test r9b, 1 + JNE LBB1_14 + JMP LBB1_15 + +TEXT ·_bitmap_aligned_and_not_sse4(SB), $0-32 + + MOVQ left+0(FP), DI + MOVQ right+8(FP), SI + MOVQ out+16(FP), DX + MOVQ length+24(FP), CX + + WORD $0x8548; BYTE $0xc9 // test rcx, rcx + JLE LBB2_16 + LONG $0x1ff98348 // cmp rcx, 31 + JA LBB2_7 + WORD $0x3145; BYTE $0xdb // xor r11d, r11d + +LBB2_3: + WORD $0x894d; BYTE $0xd8 // mov r8, r11 + WORD $0xf749; BYTE $0xd0 // not r8 + WORD $0xc1f6; BYTE $0x01 // test cl, 1 + JE LBB2_5 + LONG $0x1e048a42 // mov al, byte [rsi + r11] + WORD $0xd0f6 // not al + LONG $0x1f042242 // and al, byte [rdi + r11] + LONG $0x1a048842 // mov byte [rdx + r11], al + LONG $0x01cb8349 // or r11, 1 + +LBB2_5: + WORD $0x0149; BYTE $0xc8 // add r8, rcx + JE LBB2_16 + +LBB2_6: + LONG $0x04b60f42; BYTE $0x1e // movzx eax, byte [rsi + r11] + WORD $0xd0f6 // not al + LONG $0x1f042242 // and al, byte [rdi + r11] + LONG $0x1a048842 // mov byte [rdx + r11], al + LONG $0x44b60f42; WORD $0x011e // movzx eax, byte [rsi + r11 + 1] + WORD $0xd0f6 // not al + LONG $0x1f442242; BYTE $0x01 // and al, byte [rdi + r11 + 1] + LONG $0x1a448842; BYTE $0x01 // mov byte [rdx + r11 + 1], al + LONG $0x02c38349 // add r11, 2 + WORD $0x394c; BYTE $0xd9 // cmp rcx, r11 + JNE LBB2_6 + JMP LBB2_16 + +LBB2_7: + LONG $0x0a0c8d4c // lea r9, [rdx + rcx] + LONG $0x0f048d48 // lea rax, [rdi + rcx] + WORD $0x3948; BYTE $0xd0 // cmp rax, rdx + LONG $0xd2970f41 // seta r10b + LONG $0x0e048d48 // lea rax, [rsi + rcx] + WORD $0x3949; BYTE $0xf9 // cmp r9, rdi + WORD $0x970f; BYTE $0xd3 // seta bl + WORD $0x3948; BYTE $0xd0 // cmp rax, rdx + LONG $0xd0970f41 // seta r8b + WORD $0x3949; BYTE $0xf1 // cmp r9, rsi + LONG $0xd1970f41 // seta r9b + WORD $0x3145; BYTE $0xdb // xor r11d, r11d + WORD $0x8441; BYTE $0xda // test r10b, bl + JNE LBB2_3 + WORD $0x2045; BYTE $0xc8 // and r8b, r9b + JNE LBB2_3 + WORD $0x8949; BYTE $0xcb // mov r11, rcx + LONG $0xe0e38349 // and r11, -32 + LONG $0xe0438d49 // lea rax, [r11 - 32] + WORD $0x8949; BYTE $0xc1 // mov r9, rax + LONG $0x05e9c149 // shr r9, 5 + LONG $0x01c18349 // add r9, 1 + WORD $0x8548; BYTE $0xc0 // test rax, rax + JE LBB2_10 + WORD $0x894d; BYTE $0xca // mov r10, r9 + LONG $0xfee28349 // and r10, -2 + WORD $0xf749; BYTE $0xda // neg r10 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB2_12: + LONG $0x04100f42; BYTE $0x07 // movups xmm0, oword [rdi + r8] + LONG $0x4c100f42; WORD $0x1007 // movups xmm1, oword [rdi + r8 + 16] + LONG $0x14100f42; BYTE $0x06 // movups xmm2, oword [rsi + r8] + WORD $0x550f; BYTE $0xd0 // andnps xmm2, xmm0 + LONG $0x44100f42; WORD $0x1006 // movups xmm0, oword [rsi + r8 + 16] + WORD $0x550f; BYTE $0xc1 // andnps xmm0, xmm1 + LONG $0x14110f42; BYTE $0x02 // movups oword [rdx + r8], xmm2 + LONG $0x44110f42; WORD $0x1002 // movups oword [rdx + r8 + 16], xmm0 + LONG $0x44100f42; WORD $0x2007 // movups xmm0, oword [rdi + r8 + 32] + LONG $0x4c100f42; WORD $0x3007 // movups xmm1, oword [rdi + r8 + 48] + LONG $0x54100f42; WORD $0x2006 // movups xmm2, oword [rsi + r8 + 32] + WORD $0x550f; BYTE $0xd0 // andnps xmm2, xmm0 + LONG $0x44100f42; WORD $0x3006 // movups xmm0, oword [rsi + r8 + 48] + WORD $0x550f; BYTE $0xc1 // andnps xmm0, xmm1 + LONG $0x54110f42; WORD $0x2002 // movups oword [rdx + r8 + 32], xmm2 + LONG $0x44110f42; WORD $0x3002 // movups oword [rdx + r8 + 48], xmm0 + LONG $0x40c08349 // add r8, 64 + LONG $0x02c28349 // add r10, 2 + JNE LBB2_12 + LONG $0x01c1f641 // test r9b, 1 + JE LBB2_15 + +LBB2_14: + LONG $0x04100f42; BYTE $0x07 // movups xmm0, oword [rdi + r8] + LONG $0x4c100f42; WORD $0x1007 // movups xmm1, oword [rdi + r8 + 16] + LONG $0x14100f42; BYTE $0x06 // movups xmm2, oword [rsi + r8] + WORD $0x550f; BYTE $0xd0 // andnps xmm2, xmm0 + LONG $0x44100f42; WORD $0x1006 // movups xmm0, oword [rsi + r8 + 16] + WORD $0x550f; BYTE $0xc1 // andnps xmm0, xmm1 + LONG $0x14110f42; BYTE $0x02 // movups oword [rdx + r8], xmm2 + LONG $0x44110f42; WORD $0x1002 // movups oword [rdx + r8 + 16], xmm0 + +LBB2_15: + WORD $0x3949; BYTE $0xcb // cmp r11, rcx + JNE LBB2_3 + +LBB2_16: + RET + +LBB2_10: + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + LONG $0x01c1f641 // test r9b, 1 + JNE LBB2_14 + JMP LBB2_15 + +TEXT ·_bitmap_aligned_xor_sse4(SB), $0-32 + + MOVQ left+0(FP), DI + MOVQ right+8(FP), SI + MOVQ out+16(FP), DX + MOVQ length+24(FP), CX + + WORD $0x8548; BYTE $0xc9 // test rcx, rcx + JLE LBB3_16 + LONG $0x1ff98348 // cmp rcx, 31 + JA LBB3_7 + WORD $0x3145; BYTE $0xdb // xor r11d, r11d + +LBB3_3: + WORD $0x894d; BYTE $0xd8 // mov r8, r11 + WORD $0xf749; BYTE $0xd0 // not r8 + WORD $0x0149; BYTE $0xc8 // add r8, rcx + WORD $0x8949; BYTE $0xc9 // mov r9, rcx + LONG $0x03e18349 // and r9, 3 + JE LBB3_5 + +LBB3_4: + LONG $0x04b60f42; BYTE $0x1e // movzx eax, byte [rsi + r11] + LONG $0x1f043242 // xor al, byte [rdi + r11] + LONG $0x1a048842 // mov byte [rdx + r11], al + LONG $0x01c38349 // add r11, 1 + LONG $0xffc18349 // add r9, -1 + JNE LBB3_4 + +LBB3_5: + LONG $0x03f88349 // cmp r8, 3 + JB LBB3_16 + +LBB3_6: + LONG $0x04b60f42; BYTE $0x1e // movzx eax, byte [rsi + r11] + LONG $0x1f043242 // xor al, byte [rdi + r11] + LONG $0x1a048842 // mov byte [rdx + r11], al + LONG $0x44b60f42; WORD $0x011e // movzx eax, byte [rsi + r11 + 1] + LONG $0x1f443242; BYTE $0x01 // xor al, byte [rdi + r11 + 1] + LONG $0x1a448842; BYTE $0x01 // mov byte [rdx + r11 + 1], al + LONG $0x44b60f42; WORD $0x021e // movzx eax, byte [rsi + r11 + 2] + LONG $0x1f443242; BYTE $0x02 // xor al, byte [rdi + r11 + 2] + LONG $0x1a448842; BYTE $0x02 // mov byte [rdx + r11 + 2], al + LONG $0x44b60f42; WORD $0x031e // movzx eax, byte [rsi + r11 + 3] + LONG $0x1f443242; BYTE $0x03 // xor al, byte [rdi + r11 + 3] + LONG $0x1a448842; BYTE $0x03 // mov byte [rdx + r11 + 3], al + LONG $0x04c38349 // add r11, 4 + WORD $0x394c; BYTE $0xd9 // cmp rcx, r11 + JNE LBB3_6 + JMP LBB3_16 + +LBB3_7: + LONG $0x0a0c8d4c // lea r9, [rdx + rcx] + LONG $0x0f048d48 // lea rax, [rdi + rcx] + WORD $0x3948; BYTE $0xd0 // cmp rax, rdx + LONG $0xd2970f41 // seta r10b + LONG $0x0e048d48 // lea rax, [rsi + rcx] + WORD $0x3949; BYTE $0xf9 // cmp r9, rdi + WORD $0x970f; BYTE $0xd3 // seta bl + WORD $0x3948; BYTE $0xd0 // cmp rax, rdx + LONG $0xd0970f41 // seta r8b + WORD $0x3949; BYTE $0xf1 // cmp r9, rsi + LONG $0xd1970f41 // seta r9b + WORD $0x3145; BYTE $0xdb // xor r11d, r11d + WORD $0x8441; BYTE $0xda // test r10b, bl + JNE LBB3_3 + WORD $0x2045; BYTE $0xc8 // and r8b, r9b + JNE LBB3_3 + WORD $0x8949; BYTE $0xcb // mov r11, rcx + LONG $0xe0e38349 // and r11, -32 + LONG $0xe0438d49 // lea rax, [r11 - 32] + WORD $0x8949; BYTE $0xc1 // mov r9, rax + LONG $0x05e9c149 // shr r9, 5 + LONG $0x01c18349 // add r9, 1 + WORD $0x8548; BYTE $0xc0 // test rax, rax + JE LBB3_10 + WORD $0x894d; BYTE $0xca // mov r10, r9 + LONG $0xfee28349 // and r10, -2 + WORD $0xf749; BYTE $0xda // neg r10 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB3_12: + LONG $0x04100f42; BYTE $0x07 // movups xmm0, oword [rdi + r8] + LONG $0x4c100f42; WORD $0x1007 // movups xmm1, oword [rdi + r8 + 16] + LONG $0x14100f42; BYTE $0x06 // movups xmm2, oword [rsi + r8] + WORD $0x570f; BYTE $0xd0 // xorps xmm2, xmm0 + LONG $0x44100f42; WORD $0x1006 // movups xmm0, oword [rsi + r8 + 16] + WORD $0x570f; BYTE $0xc1 // xorps xmm0, xmm1 + LONG $0x14110f42; BYTE $0x02 // movups oword [rdx + r8], xmm2 + LONG $0x44110f42; WORD $0x1002 // movups oword [rdx + r8 + 16], xmm0 + LONG $0x44100f42; WORD $0x2007 // movups xmm0, oword [rdi + r8 + 32] + LONG $0x4c100f42; WORD $0x3007 // movups xmm1, oword [rdi + r8 + 48] + LONG $0x54100f42; WORD $0x2006 // movups xmm2, oword [rsi + r8 + 32] + WORD $0x570f; BYTE $0xd0 // xorps xmm2, xmm0 + LONG $0x44100f42; WORD $0x3006 // movups xmm0, oword [rsi + r8 + 48] + WORD $0x570f; BYTE $0xc1 // xorps xmm0, xmm1 + LONG $0x54110f42; WORD $0x2002 // movups oword [rdx + r8 + 32], xmm2 + LONG $0x44110f42; WORD $0x3002 // movups oword [rdx + r8 + 48], xmm0 + LONG $0x40c08349 // add r8, 64 + LONG $0x02c28349 // add r10, 2 + JNE LBB3_12 + LONG $0x01c1f641 // test r9b, 1 + JE LBB3_15 + +LBB3_14: + LONG $0x04100f42; BYTE $0x07 // movups xmm0, oword [rdi + r8] + LONG $0x4c100f42; WORD $0x1007 // movups xmm1, oword [rdi + r8 + 16] + LONG $0x14100f42; BYTE $0x06 // movups xmm2, oword [rsi + r8] + WORD $0x570f; BYTE $0xd0 // xorps xmm2, xmm0 + LONG $0x44100f42; WORD $0x1006 // movups xmm0, oword [rsi + r8 + 16] + WORD $0x570f; BYTE $0xc1 // xorps xmm0, xmm1 + LONG $0x14110f42; BYTE $0x02 // movups oword [rdx + r8], xmm2 + LONG $0x44110f42; WORD $0x1002 // movups oword [rdx + r8 + 16], xmm0 + +LBB3_15: + WORD $0x3949; BYTE $0xcb // cmp r11, rcx + JNE LBB3_3 + +LBB3_16: + RET + +LBB3_10: + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + LONG $0x01c1f641 // test r9b, 1 + JNE LBB3_14 + JMP LBB3_15 diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmaps.go b/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmaps.go new file mode 100644 index 000000000..2e9c0601c --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitmaps.go @@ -0,0 +1,747 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package bitutil + +import ( + "bytes" + "errors" + "math/bits" + "unsafe" + + "github.com/apache/arrow/go/v14/arrow/endian" + "github.com/apache/arrow/go/v14/arrow/internal/debug" + "github.com/apache/arrow/go/v14/arrow/memory" +) + +// BitmapReader is a simple bitmap reader for a byte slice. +type BitmapReader struct { + bitmap []byte + pos int + len int + + current byte + byteOffset int + bitOffset int +} + +// NewBitmapReader creates and returns a new bitmap reader for the given bitmap +func NewBitmapReader(bitmap []byte, offset, length int) *BitmapReader { + curbyte := byte(0) + if length > 0 && bitmap != nil { + curbyte = bitmap[offset/8] + } + return &BitmapReader{ + bitmap: bitmap, + byteOffset: offset / 8, + bitOffset: offset % 8, + current: curbyte, + len: length, + } +} + +// Set returns true if the current bit is set +func (b *BitmapReader) Set() bool { + return (b.current & (1 << b.bitOffset)) != 0 +} + +// NotSet returns true if the current bit is not set +func (b *BitmapReader) NotSet() bool { + return (b.current & (1 << b.bitOffset)) == 0 +} + +// Next advances the reader to the next bit in the bitmap. +func (b *BitmapReader) Next() { + b.bitOffset++ + b.pos++ + if b.bitOffset == 8 { + b.bitOffset = 0 + b.byteOffset++ + if b.pos < b.len { + b.current = b.bitmap[int(b.byteOffset)] + } + } +} + +// Pos returns the current bit position in the bitmap that the reader is looking at +func (b *BitmapReader) Pos() int { return b.pos } + +// Len returns the total number of bits in the bitmap +func (b *BitmapReader) Len() int { return b.len } + +// BitmapWriter is a simple writer for writing bitmaps to byte slices +type BitmapWriter struct { + buf []byte + pos int + length int + + curByte uint8 + bitMask uint8 + byteOffset int +} + +// NewBitmapWriter returns a sequential bitwise writer that preserves surrounding +// bit values as it writes. +func NewBitmapWriter(bitmap []byte, start, length int) *BitmapWriter { + ret := &BitmapWriter{ + buf: bitmap, + length: length, + byteOffset: start / 8, + bitMask: BitMask[start%8], + } + if length > 0 { + ret.curByte = bitmap[int(ret.byteOffset)] + } + return ret +} + +// Reset resets the position and view of the slice to restart writing a bitmap +// to the same byte slice. +func (b *BitmapWriter) Reset(start, length int) { + b.pos = 0 + b.byteOffset = start / 8 + b.bitMask = BitMask[start%8] + b.length = length + if b.length > 0 { + b.curByte = b.buf[int(b.byteOffset)] + } +} + +func (b *BitmapWriter) Pos() int { return b.pos } +func (b *BitmapWriter) Set() { b.curByte |= b.bitMask } +func (b *BitmapWriter) Clear() { b.curByte &= ^b.bitMask } + +// Next increments the writer to the next bit for writing. +func (b *BitmapWriter) Next() { + b.bitMask = b.bitMask << 1 + b.pos++ + if b.bitMask == 0 { + b.bitMask = 0x01 + b.buf[b.byteOffset] = b.curByte + b.byteOffset++ + if b.pos < b.length { + b.curByte = b.buf[int(b.byteOffset)] + } + } +} + +// AppendBools writes a series of booleans to the bitmapwriter and returns +// the number of remaining bytes left in the buffer for writing. +func (b *BitmapWriter) AppendBools(in []bool) int { + space := min(b.length-b.pos, len(in)) + if space == 0 { + return 0 + } + + bitOffset := bits.TrailingZeros32(uint32(b.bitMask)) + // location that the first byte needs to be written to for appending + appslice := b.buf[int(b.byteOffset) : b.byteOffset+int(BytesForBits(int64(bitOffset+space)))] + // update everything but curByte + appslice[0] = b.curByte + for i, b := range in[:space] { + if b { + SetBit(appslice, i+bitOffset) + } else { + ClearBit(appslice, i+bitOffset) + } + } + + b.pos += space + b.bitMask = BitMask[(bitOffset+space)%8] + b.byteOffset += (bitOffset + space) / 8 + b.curByte = appslice[len(appslice)-1] + + return space +} + +// Finish flushes the final byte out to the byteslice in case it was not already +// on a byte aligned boundary. +func (b *BitmapWriter) Finish() { + if b.length > 0 && (b.bitMask != 0x01 || b.pos < b.length) { + b.buf[int(b.byteOffset)] = b.curByte + } +} + +// BitmapWordReader is a reader for bitmaps that reads a word at a time (a word being an 8 byte uint64) +// and then provides functions to grab the individual trailing bytes after the last word +type BitmapWordReader struct { + bitmap []byte + offset int + nwords int + trailingBits int + trailingBytes int + curword uint64 +} + +// NewBitmapWordReader sets up a word reader, calculates the number of trailing bits and +// number of trailing bytes, along with the number of words. +func NewBitmapWordReader(bitmap []byte, offset, length int) *BitmapWordReader { + bitoffset := offset % 8 + byteOffset := offset / 8 + bm := &BitmapWordReader{ + offset: bitoffset, + bitmap: bitmap[byteOffset : byteOffset+int(BytesForBits(int64(bitoffset+length)))], + // decrement wordcount by 1 as we may touch two adjacent words in one iteration + nwords: length/int(unsafe.Sizeof(uint64(0))*8) - 1, + } + if bm.nwords < 0 { + bm.nwords = 0 + } + bm.trailingBits = length - bm.nwords*int(unsafe.Sizeof(uint64(0)))*8 + bm.trailingBytes = int(BytesForBits(int64(bm.trailingBits))) + + if bm.nwords > 0 { + bm.curword = toFromLEFunc(endian.Native.Uint64(bm.bitmap)) + } else if length > 0 { + setLSB(&bm.curword, bm.bitmap[0]) + } + return bm +} + +// NextWord returns the next full word read from the bitmap, should not be called +// if Words() is 0 as it will step outside of the bounds of the bitmap slice and panic. +// +// We don't perform the bounds checking in order to improve performance. +func (bm *BitmapWordReader) NextWord() uint64 { + bm.bitmap = bm.bitmap[unsafe.Sizeof(bm.curword):] + word := bm.curword + nextWord := toFromLEFunc(endian.Native.Uint64(bm.bitmap)) + if bm.offset != 0 { + // combine two adjacent words into one word + // |<------ next ----->|<---- current ---->| + // +-------------+-----+-------------+-----+ + // | --- | A | B | --- | + // +-------------+-----+-------------+-----+ + // | | offset + // v v + // +-----+-------------+ + // | A | B | + // +-----+-------------+ + // |<------ word ----->| + word >>= uint64(bm.offset) + word |= nextWord << (int64(unsafe.Sizeof(uint64(0))*8) - int64(bm.offset)) + } + bm.curword = nextWord + return word +} + +// NextTrailingByte returns the next trailing byte of the bitmap after the last word +// along with the number of valid bits in that byte. When validBits < 8, that +// is the last byte. +// +// If the bitmap ends on a byte alignment, then the last byte can also return 8 valid bits. +// Thus the TrailingBytes function should be used to know how many trailing bytes to read. +func (bm *BitmapWordReader) NextTrailingByte() (val byte, validBits int) { + debug.Assert(bm.trailingBits > 0, "next trailing byte called with no trailing bits") + + if bm.trailingBits <= 8 { + // last byte + validBits = bm.trailingBits + bm.trailingBits = 0 + rdr := NewBitmapReader(bm.bitmap, bm.offset, validBits) + for i := 0; i < validBits; i++ { + val >>= 1 + if rdr.Set() { + val |= 0x80 + } + rdr.Next() + } + val >>= (8 - validBits) + return + } + + bm.bitmap = bm.bitmap[1:] + nextByte := bm.bitmap[0] + val = getLSB(bm.curword) + if bm.offset != 0 { + val >>= byte(bm.offset) + val |= nextByte << (8 - bm.offset) + } + setLSB(&bm.curword, nextByte) + bm.trailingBits -= 8 + bm.trailingBytes-- + validBits = 8 + return +} + +func (bm *BitmapWordReader) Words() int { return bm.nwords } +func (bm *BitmapWordReader) TrailingBytes() int { return bm.trailingBytes } + +// BitmapWordWriter is a bitmap writer for writing a full word at a time (a word being +// a uint64). After the last full word is written, PutNextTrailingByte can be used to +// write the remaining trailing bytes. +type BitmapWordWriter struct { + bitmap []byte + offset int + len int + + bitMask uint64 + currentWord uint64 +} + +// NewBitmapWordWriter initializes a new bitmap word writer which will start writing +// into the byte slice at bit offset start, expecting to write len bits. +func NewBitmapWordWriter(bitmap []byte, start, len int) *BitmapWordWriter { + ret := &BitmapWordWriter{ + bitmap: bitmap[start/8:], + len: len, + offset: start % 8, + bitMask: (uint64(1) << uint64(start%8)) - 1, + } + + if ret.offset != 0 { + if ret.len >= int(unsafe.Sizeof(uint64(0))*8) { + ret.currentWord = toFromLEFunc(endian.Native.Uint64(ret.bitmap)) + } else if ret.len > 0 { + setLSB(&ret.currentWord, ret.bitmap[0]) + } + } + return ret +} + +// PutNextWord writes the given word to the bitmap, potentially splitting across +// two adjacent words. +func (bm *BitmapWordWriter) PutNextWord(word uint64) { + sz := int(unsafe.Sizeof(word)) + if bm.offset != 0 { + // split one word into two adjacent words, don't touch unused bits + // |<------ word ----->| + // +-----+-------------+ + // | A | B | + // +-----+-------------+ + // | | + // v v offset + // +-------------+-----+-------------+-----+ + // | --- | A | B | --- | + // +-------------+-----+-------------+-----+ + // |<------ next ----->|<---- current ---->| + word = (word << uint64(bm.offset)) | (word >> (int64(sz*8) - int64(bm.offset))) + next := toFromLEFunc(endian.Native.Uint64(bm.bitmap[sz:])) + bm.currentWord = (bm.currentWord & bm.bitMask) | (word &^ bm.bitMask) + next = (next &^ bm.bitMask) | (word & bm.bitMask) + endian.Native.PutUint64(bm.bitmap, toFromLEFunc(bm.currentWord)) + endian.Native.PutUint64(bm.bitmap[sz:], toFromLEFunc(next)) + bm.currentWord = next + } else { + endian.Native.PutUint64(bm.bitmap, toFromLEFunc(word)) + } + bm.bitmap = bm.bitmap[sz:] +} + +// PutNextTrailingByte writes the number of bits indicated by validBits from b to +// the bitmap. +func (bm *BitmapWordWriter) PutNextTrailingByte(b byte, validBits int) { + curbyte := getLSB(bm.currentWord) + if validBits == 8 { + if bm.offset != 0 { + b = (b << bm.offset) | (b >> (8 - bm.offset)) + next := bm.bitmap[1] + curbyte = (curbyte & byte(bm.bitMask)) | (b &^ byte(bm.bitMask)) + next = (next &^ byte(bm.bitMask)) | (b & byte(bm.bitMask)) + bm.bitmap[0] = curbyte + bm.bitmap[1] = next + bm.currentWord = uint64(next) + } else { + bm.bitmap[0] = b + } + bm.bitmap = bm.bitmap[1:] + } else { + debug.Assert(validBits > 0 && validBits < 8, "invalid valid bits in bitmap word writer") + debug.Assert(BytesForBits(int64(bm.offset+validBits)) <= int64(len(bm.bitmap)), "writing trailiing byte outside of bounds of bitmap") + wr := NewBitmapWriter(bm.bitmap, int(bm.offset), validBits) + for i := 0; i < validBits; i++ { + if b&0x01 != 0 { + wr.Set() + } else { + wr.Clear() + } + wr.Next() + b >>= 1 + } + wr.Finish() + } +} + +type transferMode int8 + +const ( + transferCopy transferMode = iota + transferInvert +) + +func transferBitmap(mode transferMode, src []byte, srcOffset, length int, dst []byte, dstOffset int) { + if length == 0 { + // if there's nothing to write, end early. + return + } + + bitOffset := srcOffset % 8 + destBitOffset := dstOffset % 8 + + // slow path, one of the bitmaps are not byte aligned. + if bitOffset != 0 || destBitOffset != 0 { + rdr := NewBitmapWordReader(src, srcOffset, length) + wr := NewBitmapWordWriter(dst, dstOffset, length) + + nwords := rdr.Words() + for nwords > 0 { + nwords-- + if mode == transferInvert { + wr.PutNextWord(^rdr.NextWord()) + } else { + wr.PutNextWord(rdr.NextWord()) + } + } + nbytes := rdr.TrailingBytes() + for nbytes > 0 { + nbytes-- + bt, validBits := rdr.NextTrailingByte() + if mode == transferInvert { + bt = ^bt + } + wr.PutNextTrailingByte(bt, validBits) + } + return + } + + // fast path, both are starting with byte-aligned bitmaps + nbytes := int(BytesForBits(int64(length))) + + // shift by its byte offset + src = src[srcOffset/8:] + dst = dst[dstOffset/8:] + + // Take care of the trailing bits in the last byte + // E.g., if trailing_bits = 5, last byte should be + // - low 3 bits: new bits from last byte of data buffer + // - high 5 bits: old bits from last byte of dest buffer + trailingBits := nbytes*8 - length + trailMask := byte(uint(1)<<(8-trailingBits)) - 1 + var lastData byte + if mode == transferInvert { + for i, b := range src[:nbytes-1] { + dst[i] = ^b + } + lastData = ^src[nbytes-1] + } else { + copy(dst, src[:nbytes-1]) + lastData = src[nbytes-1] + } + + dst[nbytes-1] &= ^trailMask + dst[nbytes-1] |= lastData & trailMask +} + +// CopyBitmap copies the bitmap indicated by src, starting at bit offset srcOffset, +// and copying length bits into dst, starting at bit offset dstOffset. +func CopyBitmap(src []byte, srcOffset, length int, dst []byte, dstOffset int) { + transferBitmap(transferCopy, src, srcOffset, length, dst, dstOffset) +} + +// InvertBitmap copies a bit range of a bitmap, inverting it as it copies +// over into the destination. +func InvertBitmap(src []byte, srcOffset, length int, dst []byte, dstOffset int) { + transferBitmap(transferInvert, src, srcOffset, length, dst, dstOffset) +} + +type bitOp struct { + opWord func(uint64, uint64) uint64 + opByte func(byte, byte) byte + opAligned func(l, r, o []byte) +} + +var ( + bitAndOp = bitOp{ + opWord: func(l, r uint64) uint64 { return l & r }, + opByte: func(l, r byte) byte { return l & r }, + } + bitOrOp = bitOp{ + opWord: func(l, r uint64) uint64 { return l | r }, + opByte: func(l, r byte) byte { return l | r }, + } + bitAndNotOp = bitOp{ + opWord: func(l, r uint64) uint64 { return l &^ r }, + opByte: func(l, r byte) byte { return l &^ r }, + } + bitXorOp = bitOp{ + opWord: func(l, r uint64) uint64 { return l ^ r }, + opByte: func(l, r byte) byte { return l ^ r }, + } +) + +func alignedBitmapOp(op bitOp, left, right []byte, lOffset, rOffset int64, out []byte, outOffset int64, length int64) { + debug.Assert(lOffset%8 == rOffset%8, "aligned bitmap op called with unaligned offsets") + debug.Assert(lOffset%8 == outOffset%8, "aligned bitmap op called with unaligned output offset") + + nbytes := BytesForBits(length + lOffset%8) + left = left[lOffset/8:] + right = right[rOffset/8:] + out = out[outOffset/8:] + endMask := (lOffset + length%8) + switch nbytes { + case 0: + return + case 1: // everything within a single byte + // (length+lOffset%8) <= 8 + mask := PrecedingBitmask[lOffset%8] + if endMask != 0 { + mask |= TrailingBitmask[(lOffset+length)%8] + } + out[0] = (out[0] & mask) | (op.opByte(left[0], right[0]) &^ mask) + case 2: // don't send zero length to opAligned + firstByteMask := PrecedingBitmask[lOffset%8] + out[0] = (out[0] & firstByteMask) | (op.opByte(left[0], right[0]) &^ firstByteMask) + lastByteMask := byte(0) + if endMask != 0 { + lastByteMask = TrailingBitmask[(lOffset+length)%8] + } + out[1] = (out[1] & lastByteMask) | (op.opByte(left[1], right[1]) &^ lastByteMask) + default: + firstByteMask := PrecedingBitmask[lOffset%8] + out[0] = (out[0] & firstByteMask) | (op.opByte(left[0], right[0]) &^ firstByteMask) + + op.opAligned(left[1:nbytes-1], right[1:nbytes-1], out[1:nbytes-1]) + + lastByteMask := byte(0) + if endMask != 0 { + lastByteMask = TrailingBitmask[(lOffset+length)%8] + } + out[nbytes-1] = (out[nbytes-1] & lastByteMask) | (op.opByte(left[nbytes-1], right[nbytes-1]) &^ lastByteMask) + } +} + +func unalignedBitmapOp(op bitOp, left, right []byte, lOffset, rOffset int64, out []byte, outOffset int64, length int64) { + leftRdr := NewBitmapWordReader(left, int(lOffset), int(length)) + rightRdr := NewBitmapWordReader(right, int(rOffset), int(length)) + writer := NewBitmapWordWriter(out, int(outOffset), int(length)) + + for nwords := leftRdr.Words(); nwords > 0; nwords-- { + writer.PutNextWord(op.opWord(leftRdr.NextWord(), rightRdr.NextWord())) + } + for nbytes := leftRdr.TrailingBytes(); nbytes > 0; nbytes-- { + leftByte, leftValid := leftRdr.NextTrailingByte() + rightByte, rightValid := rightRdr.NextTrailingByte() + debug.Assert(leftValid == rightValid, "unexpected mismatch of valid bits") + writer.PutNextTrailingByte(op.opByte(leftByte, rightByte), leftValid) + } +} + +func BitmapOp(op bitOp, left, right []byte, lOffset, rOffset int64, out []byte, outOffset, length int64) { + if (outOffset%8 == lOffset%8) && (outOffset%8 == rOffset%8) { + // fastcase! + alignedBitmapOp(op, left, right, lOffset, rOffset, out, outOffset, length) + } else { + unalignedBitmapOp(op, left, right, lOffset, rOffset, out, outOffset, length) + } +} + +func BitmapOpAlloc(mem memory.Allocator, op bitOp, left, right []byte, lOffset, rOffset int64, length int64, outOffset int64) *memory.Buffer { + bits := length + outOffset + buf := memory.NewResizableBuffer(mem) + buf.Resize(int(BytesForBits(bits))) + BitmapOp(op, left, right, lOffset, rOffset, buf.Bytes(), outOffset, length) + return buf +} + +func BitmapAnd(left, right []byte, lOffset, rOffset int64, out []byte, outOffset int64, length int64) { + BitmapOp(bitAndOp, left, right, lOffset, rOffset, out, outOffset, length) +} + +func BitmapOr(left, right []byte, lOffset, rOffset int64, out []byte, outOffset int64, length int64) { + BitmapOp(bitOrOp, left, right, lOffset, rOffset, out, outOffset, length) +} + +func BitmapAndAlloc(mem memory.Allocator, left, right []byte, lOffset, rOffset int64, length, outOffset int64) *memory.Buffer { + return BitmapOpAlloc(mem, bitAndOp, left, right, lOffset, rOffset, length, outOffset) +} + +func BitmapOrAlloc(mem memory.Allocator, left, right []byte, lOffset, rOffset int64, length, outOffset int64) *memory.Buffer { + return BitmapOpAlloc(mem, bitOrOp, left, right, lOffset, rOffset, length, outOffset) +} + +func BitmapAndNot(left, right []byte, lOffset, rOffset int64, out []byte, outOffset int64, length int64) { + BitmapOp(bitAndNotOp, left, right, lOffset, rOffset, out, outOffset, length) +} + +func BitmapAndNotAlloc(mem memory.Allocator, left, right []byte, lOffset, rOffset int64, length, outOffset int64) *memory.Buffer { + return BitmapOpAlloc(mem, bitAndNotOp, left, right, lOffset, rOffset, length, outOffset) +} + +func BitmapXor(left, right []byte, lOffset, rOffset int64, out []byte, outOffset int64, length int64) { + BitmapOp(bitXorOp, left, right, lOffset, rOffset, out, outOffset, length) +} + +func BitmapXorAlloc(mem memory.Allocator, left, right []byte, lOffset, rOffset int64, length, outOffset int64) *memory.Buffer { + return BitmapOpAlloc(mem, bitXorOp, left, right, lOffset, rOffset, length, outOffset) +} + +func BitmapEquals(left, right []byte, lOffset, rOffset int64, length int64) bool { + if lOffset%8 == 0 && rOffset%8 == 0 { + // byte aligned, fast path, can use bytes.Equal (memcmp) + byteLen := length / 8 + lStart := lOffset / 8 + rStart := rOffset / 8 + if !bytes.Equal(left[lStart:lStart+byteLen], right[rStart:rStart+byteLen]) { + return false + } + + // check trailing bits + for i := (length / 8) * 8; i < length; i++ { + if BitIsSet(left, int(lOffset+i)) != BitIsSet(right, int(rOffset+i)) { + return false + } + } + return true + } + + lrdr := NewBitmapWordReader(left, int(lOffset), int(length)) + rrdr := NewBitmapWordReader(right, int(rOffset), int(length)) + + nwords := lrdr.Words() + for nwords > 0 { + nwords-- + if lrdr.NextWord() != rrdr.NextWord() { + return false + } + } + + nbytes := lrdr.TrailingBytes() + for nbytes > 0 { + nbytes-- + lbt, _ := lrdr.NextTrailingByte() + rbt, _ := rrdr.NextTrailingByte() + if lbt != rbt { + return false + } + } + return true +} + +// OptionalBitIndexer is a convenience wrapper for getting bits from +// a bitmap which may or may not be nil. +type OptionalBitIndexer struct { + Bitmap []byte + Offset int +} + +func (b *OptionalBitIndexer) GetBit(i int) bool { + return b.Bitmap == nil || BitIsSet(b.Bitmap, b.Offset+i) +} + +type Bitmap struct { + Data []byte + Offset, Len int64 +} + +func bitLength(bitmaps []Bitmap) (int64, error) { + for _, b := range bitmaps[1:] { + if b.Len != bitmaps[0].Len { + return -1, errors.New("bitmaps must be same length") + } + } + return bitmaps[0].Len, nil +} + +func runVisitWordsAndWriteLoop(bitLen int64, rdrs []*BitmapWordReader, wrs []*BitmapWordWriter, visitor func(in, out []uint64)) { + const bitWidth int64 = int64(uint64SizeBits) + + visited := make([]uint64, len(rdrs)) + output := make([]uint64, len(wrs)) + + // every reader will have same number of words, since they are same + // length'ed. This will be inefficient in some cases. When there's + // offsets beyond the Word boundary, every word would have to be + // created from 2 adjoining words + nwords := int64(rdrs[0].Words()) + bitLen -= nwords * bitWidth + for nwords > 0 { + nwords-- + for i := range visited { + visited[i] = rdrs[i].NextWord() + } + visitor(visited, output) + for i := range output { + wrs[i].PutNextWord(output[i]) + } + } + + // every reader will have the same number of trailing bytes, because + // we already confirmed they have the same length. Because + // offsets beyond the Word boundary can cause adjoining words, the + // tailing portion could be more than one word remaining full/partial + // words to write. + if bitLen == 0 { + return + } + + // convert the word visitor to a bytevisitor + byteVisitor := func(in, out []byte) { + for i, w := range in { + visited[i] = uint64(w) + } + visitor(visited, output) + for i, w := range output { + out[i] = byte(w) + } + } + + visitedBytes := make([]byte, len(rdrs)) + outputBytes := make([]byte, len(wrs)) + nbytes := rdrs[0].trailingBytes + for nbytes > 0 { + nbytes-- + memory.Set(visitedBytes, 0) + memory.Set(outputBytes, 0) + + var validBits int + for i := range rdrs { + visitedBytes[i], validBits = rdrs[i].NextTrailingByte() + } + byteVisitor(visitedBytes, outputBytes) + for i, w := range outputBytes { + wrs[i].PutNextTrailingByte(w, validBits) + } + } +} + +// VisitWordsAndWrite visits words of bits from each input bitmap and +// collects outputs to a slice of output Bitmaps. +// +// All bitmaps must have identical lengths. The first bit in a visited +// bitmap may be offset within the first visited word, but words will +// otherwise contain densely packed bits loaded from the bitmap. That +// offset within the first word is returned. +// +// NOTE: this function is efficient on 3+ sufficiently large bitmaps. +// It also has a large prolog/epilog overhead and should be used +// carefully in other cases. For 2 or fewer bitmaps, and/or smaller +// bitmaps, try BitmapReader and or other utilities. +func VisitWordsAndWrite(args []Bitmap, out []Bitmap, visitor func(in, out []uint64)) error { + bitLen, err := bitLength(args) + if err != nil { + return err + } + + rdrs, wrs := make([]*BitmapWordReader, len(args)), make([]*BitmapWordWriter, len(out)) + for i, in := range args { + rdrs[i] = NewBitmapWordReader(in.Data, int(in.Offset), int(in.Len)) + } + for i, o := range out { + wrs[i] = NewBitmapWordWriter(o.Data, int(o.Offset), int(o.Len)) + } + runVisitWordsAndWriteLoop(bitLen, rdrs, wrs, visitor) + return nil +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitutil.go b/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitutil.go new file mode 100644 index 000000000..a4a1519b8 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/bitutil.go @@ -0,0 +1,217 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package bitutil + +import ( + "math" + "math/bits" + "reflect" + "unsafe" + + "github.com/apache/arrow/go/v14/arrow/memory" +) + +var ( + BitMask = [8]byte{1, 2, 4, 8, 16, 32, 64, 128} + FlippedBitMask = [8]byte{254, 253, 251, 247, 239, 223, 191, 127} +) + +// IsMultipleOf8 returns whether v is a multiple of 8. +func IsMultipleOf8(v int64) bool { return v&7 == 0 } + +// IsMultipleOf64 returns whether v is a multiple of 64 +func IsMultipleOf64(v int64) bool { return v&63 == 0 } + +func BytesForBits(bits int64) int64 { return (bits + 7) >> 3 } + +// NextPowerOf2 rounds x to the next power of two. +func NextPowerOf2(x int) int { return 1 << uint(bits.Len(uint(x))) } + +// CeilByte rounds size to the next multiple of 8. +func CeilByte(size int) int { return (size + 7) &^ 7 } + +// CeilByte64 rounds size to the next multiple of 8. +func CeilByte64(size int64) int64 { return (size + 7) &^ 7 } + +// BitIsSet returns true if the bit at index i in buf is set (1). +func BitIsSet(buf []byte, i int) bool { return (buf[uint(i)/8] & BitMask[byte(i)%8]) != 0 } + +// BitIsNotSet returns true if the bit at index i in buf is not set (0). +func BitIsNotSet(buf []byte, i int) bool { return (buf[uint(i)/8] & BitMask[byte(i)%8]) == 0 } + +// SetBit sets the bit at index i in buf to 1. +func SetBit(buf []byte, i int) { buf[uint(i)/8] |= BitMask[byte(i)%8] } + +// ClearBit sets the bit at index i in buf to 0. +func ClearBit(buf []byte, i int) { buf[uint(i)/8] &= FlippedBitMask[byte(i)%8] } + +// SetBitTo sets the bit at index i in buf to val. +func SetBitTo(buf []byte, i int, val bool) { + if val { + SetBit(buf, i) + } else { + ClearBit(buf, i) + } +} + +// CountSetBits counts the number of 1's in buf up to n bits. +func CountSetBits(buf []byte, offset, n int) int { + if offset > 0 { + return countSetBitsWithOffset(buf, offset, n) + } + + count := 0 + + uint64Bytes := n / uint64SizeBits * 8 + for _, v := range bytesToUint64(buf[:uint64Bytes]) { + count += bits.OnesCount64(v) + } + + for _, v := range buf[uint64Bytes : n/8] { + count += bits.OnesCount8(v) + } + + // tail bits + for i := n &^ 0x7; i < n; i++ { + if BitIsSet(buf, i) { + count++ + } + } + + return count +} + +func countSetBitsWithOffset(buf []byte, offset, n int) int { + count := 0 + + beg := offset + end := offset + n + + begU8 := roundUp(beg, uint64SizeBits) + + init := min(n, begU8-beg) + for i := offset; i < beg+init; i++ { + if BitIsSet(buf, i) { + count++ + } + } + + nU64 := (n - init) / uint64SizeBits + begU64 := begU8 / uint64SizeBits + endU64 := begU64 + nU64 + bufU64 := bytesToUint64(buf) + if begU64 < len(bufU64) { + for _, v := range bufU64[begU64:endU64] { + count += bits.OnesCount64(v) + } + } + + // FIXME: use a fallback to bits.OnesCount8 + // before counting the tail bits. + + tail := beg + init + nU64*uint64SizeBits + for i := tail; i < end; i++ { + if BitIsSet(buf, i) { + count++ + } + } + + return count +} + +func roundUp(v, f int) int { + return (v + (f - 1)) / f * f +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +const ( + uint64SizeBytes = int(unsafe.Sizeof(uint64(0))) + uint64SizeBits = uint64SizeBytes * 8 +) + +func bytesToUint64(b []byte) []uint64 { + if cap(b) < uint64SizeBytes { + return nil + } + + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + return unsafe.Slice((*uint64)(unsafe.Pointer(h.Data)), cap(b)/uint64SizeBytes)[:len(b)/uint64SizeBytes] +} + +var ( + // PrecedingBitmask is a convenience set of values as bitmasks for checking + // prefix bits of a byte + PrecedingBitmask = [8]byte{0, 1, 3, 7, 15, 31, 63, 127} + // TrailingBitmask is the bitwise complement version of kPrecedingBitmask + TrailingBitmask = [8]byte{255, 254, 252, 248, 240, 224, 192, 128} +) + +// SetBitsTo is a convenience function to quickly set or unset all the bits +// in a bitmap starting at startOffset for length bits. +func SetBitsTo(bits []byte, startOffset, length int64, areSet bool) { + if length == 0 { + return + } + + beg := startOffset + end := startOffset + length + var fill uint8 = 0 + if areSet { + fill = math.MaxUint8 + } + + byteBeg := beg / 8 + byteEnd := end/8 + 1 + + // don't modify bits before the startOffset by using this mask + firstByteMask := PrecedingBitmask[beg%8] + // don't modify bits past the length by using this mask + lastByteMask := TrailingBitmask[end%8] + + if byteEnd == byteBeg+1 { + // set bits within a single byte + onlyByteMask := firstByteMask + if end%8 != 0 { + onlyByteMask = firstByteMask | lastByteMask + } + + bits[byteBeg] &= onlyByteMask + bits[byteBeg] |= fill &^ onlyByteMask + return + } + + // set/clear trailing bits of first byte + bits[byteBeg] &= firstByteMask + bits[byteBeg] |= fill &^ firstByteMask + + if byteEnd-byteBeg > 2 { + memory.Set(bits[byteBeg+1:byteEnd-1], fill) + } + + if end%8 == 0 { + return + } + + bits[byteEnd-1] &= lastByteMask + bits[byteEnd-1] |= fill &^ lastByteMask +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/endian_default.go b/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/endian_default.go new file mode 100644 index 000000000..9f5d3cdc7 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/endian_default.go @@ -0,0 +1,33 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build !s390x + +package bitutil + +import ( + "unsafe" +) + +var toFromLEFunc = func(in uint64) uint64 { return in } + +func getLSB(v uint64) byte { + return (*[8]byte)(unsafe.Pointer(&v))[0] +} + +func setLSB(v *uint64, b byte) { + (*[8]byte)(unsafe.Pointer(v))[0] = b +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/endian_s390x.go b/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/endian_s390x.go new file mode 100644 index 000000000..a9bba4391 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/bitutil/endian_s390x.go @@ -0,0 +1,32 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package bitutil + +import ( + "math/bits" + "unsafe" +) + +var toFromLEFunc = bits.ReverseBytes64 + +func getLSB(v uint64) byte { + return (*[8]byte)(unsafe.Pointer(&v))[7] +} + +func setLSB(v *uint64, b byte) { + (*[8]byte)(unsafe.Pointer(v))[7] = b +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/compare.go b/vendor/github.com/apache/arrow/go/v14/arrow/compare.go new file mode 100644 index 000000000..58569b332 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/compare.go @@ -0,0 +1,153 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package arrow + +import ( + "reflect" +) + +type typeEqualsConfig struct { + metadata bool +} + +// TypeEqualOption is a functional option type used for configuring type +// equality checks. +type TypeEqualOption func(*typeEqualsConfig) + +// CheckMetadata is an option for TypeEqual that allows checking for metadata +// equality besides type equality. It only makes sense for types with metadata. +func CheckMetadata() TypeEqualOption { + return func(cfg *typeEqualsConfig) { + cfg.metadata = true + } +} + +// TypeEqual checks if two DataType are the same, optionally checking metadata +// equality for STRUCT types. +func TypeEqual(left, right DataType, opts ...TypeEqualOption) bool { + var cfg typeEqualsConfig + for _, opt := range opts { + opt(&cfg) + } + + switch { + case left == nil || right == nil: + return left == nil && right == nil + case left.ID() != right.ID(): + return false + } + + switch l := left.(type) { + case ExtensionType: + return l.ExtensionEquals(right.(ExtensionType)) + case *ListType: + if !TypeEqual(l.Elem(), right.(*ListType).Elem(), opts...) { + return false + } + if cfg.metadata && !l.elem.Metadata.Equal(right.(*ListType).elem.Metadata) { + return false + } + return l.elem.Nullable == right.(*ListType).elem.Nullable + case *FixedSizeListType: + if !TypeEqual(l.Elem(), right.(*FixedSizeListType).Elem(), opts...) { + return false + } + if cfg.metadata && !l.elem.Metadata.Equal(right.(*FixedSizeListType).elem.Metadata) { + return false + } + return l.n == right.(*FixedSizeListType).n && l.elem.Nullable == right.(*FixedSizeListType).elem.Nullable + case *MapType: + if !TypeEqual(l.KeyType(), right.(*MapType).KeyType(), opts...) { + return false + } + if !TypeEqual(l.ItemType(), right.(*MapType).ItemType(), opts...) { + return false + } + if l.KeyField().Nullable != right.(*MapType).KeyField().Nullable { + return false + } + if l.ItemField().Nullable != right.(*MapType).ItemField().Nullable { + return false + } + if cfg.metadata { + if !l.KeyField().Metadata.Equal(right.(*MapType).KeyField().Metadata) { + return false + } + if !l.ItemField().Metadata.Equal(right.(*MapType).ItemField().Metadata) { + return false + } + } + return true + case *StructType: + r := right.(*StructType) + switch { + case len(l.fields) != len(r.fields): + return false + case !reflect.DeepEqual(l.index, r.index): + return false + } + for i := range l.fields { + leftField, rightField := l.fields[i], r.fields[i] + switch { + case leftField.Name != rightField.Name: + return false + case leftField.Nullable != rightField.Nullable: + return false + case !TypeEqual(leftField.Type, rightField.Type, opts...): + return false + case cfg.metadata && !leftField.Metadata.Equal(rightField.Metadata): + return false + } + } + return true + case UnionType: + r := right.(UnionType) + if l.Mode() != r.Mode() { + return false + } + + if !reflect.DeepEqual(l.ChildIDs(), r.ChildIDs()) { + return false + } + + for i := range l.Fields() { + leftField, rightField := l.Fields()[i], r.Fields()[i] + switch { + case leftField.Name != rightField.Name: + return false + case leftField.Nullable != rightField.Nullable: + return false + case !TypeEqual(leftField.Type, rightField.Type, opts...): + return false + case cfg.metadata && !leftField.Metadata.Equal(rightField.Metadata): + return false + case l.TypeCodes()[i] != r.TypeCodes()[i]: + return false + } + } + return true + case *TimestampType: + r := right.(*TimestampType) + return l.Unit == r.Unit && l.TimeZone == r.TimeZone + case *RunEndEncodedType: + r := right.(*RunEndEncodedType) + return TypeEqual(l.Encoded(), r.Encoded(), opts...) && + TypeEqual(l.runEnds, r.runEnds, opts...) + default: + return reflect.DeepEqual(left, right) + } +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/datatype.go b/vendor/github.com/apache/arrow/go/v14/arrow/datatype.go new file mode 100644 index 000000000..f0fb24ec8 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/datatype.go @@ -0,0 +1,404 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package arrow + +import ( + "fmt" + "hash/maphash" + "strings" + + "github.com/apache/arrow/go/v14/arrow/internal/debug" +) + +// Type is a logical type. They can be expressed as +// either a primitive physical type (bytes or bits of some fixed size), a +// nested type consisting of other data types, or another data type (e.g. a +// timestamp encoded as an int64) +type Type int + +const ( + // NULL type having no physical storage + NULL Type = iota + + // BOOL is a 1 bit, LSB bit-packed ordering + BOOL + + // UINT8 is an Unsigned 8-bit little-endian integer + UINT8 + + // INT8 is a Signed 8-bit little-endian integer + INT8 + + // UINT16 is an Unsigned 16-bit little-endian integer + UINT16 + + // INT16 is a Signed 16-bit little-endian integer + INT16 + + // UINT32 is an Unsigned 32-bit little-endian integer + UINT32 + + // INT32 is a Signed 32-bit little-endian integer + INT32 + + // UINT64 is an Unsigned 64-bit little-endian integer + UINT64 + + // INT64 is a Signed 64-bit little-endian integer + INT64 + + // FLOAT16 is a 2-byte floating point value + FLOAT16 + + // FLOAT32 is a 4-byte floating point value + FLOAT32 + + // FLOAT64 is an 8-byte floating point value + FLOAT64 + + // STRING is a UTF8 variable-length string + STRING + + // BINARY is a Variable-length byte type (no guarantee of UTF8-ness) + BINARY + + // FIXED_SIZE_BINARY is a binary where each value occupies the same number of bytes + FIXED_SIZE_BINARY + + // DATE32 is int32 days since the UNIX epoch + DATE32 + + // DATE64 is int64 milliseconds since the UNIX epoch + DATE64 + + // TIMESTAMP is an exact timestamp encoded with int64 since UNIX epoch + // Default unit millisecond + TIMESTAMP + + // TIME32 is a signed 32-bit integer, representing either seconds or + // milliseconds since midnight + TIME32 + + // TIME64 is a signed 64-bit integer, representing either microseconds or + // nanoseconds since midnight + TIME64 + + // INTERVAL_MONTHS is YEAR_MONTH interval in SQL style + INTERVAL_MONTHS + + // INTERVAL_DAY_TIME is DAY_TIME in SQL Style + INTERVAL_DAY_TIME + + // DECIMAL128 is a precision- and scale-based decimal type. Storage type depends on the + // parameters. + DECIMAL128 + + // DECIMAL256 is a precision and scale based decimal type, with 256 bit max. not yet implemented + DECIMAL256 + + // LIST is a list of some logical data type + LIST + + // STRUCT of logical types + STRUCT + + // SPARSE_UNION of logical types. not yet implemented + SPARSE_UNION + + // DENSE_UNION of logical types. not yet implemented + DENSE_UNION + + // DICTIONARY aka Category type + DICTIONARY + + // MAP is a repeated struct logical type + MAP + + // Custom data type, implemented by user + EXTENSION + + // Fixed size list of some logical type + FIXED_SIZE_LIST + + // Measure of elapsed time in either seconds, milliseconds, microseconds + // or nanoseconds. + DURATION + + // like STRING, but 64-bit offsets. not yet implemented + LARGE_STRING + + // like BINARY but with 64-bit offsets, not yet implemented + LARGE_BINARY + + // like LIST but with 64-bit offsets. not yet implmented + LARGE_LIST + + // calendar interval with three fields + INTERVAL_MONTH_DAY_NANO + + RUN_END_ENCODED + + // String (UTF8) view type with 4-byte prefix and inline + // small string optimizations + STRING_VIEW + + // Bytes view with 4-byte prefix and inline small byte arrays optimization + BINARY_VIEW + + // LIST_VIEW is a list of some logical data type represented with offsets and sizes + LIST_VIEW + + // like LIST but with 64-bit offsets + LARGE_LIST_VIEW + + // Alias to ensure we do not break any consumers + DECIMAL = DECIMAL128 +) + +// DataType is the representation of an Arrow type. +type DataType interface { + fmt.Stringer + ID() Type + // Name is name of the data type. + Name() string + Fingerprint() string + Layout() DataTypeLayout +} + +// TypesToString is a convenience function to create a list of types +// which are comma delimited as a string +func TypesToString(types []DataType) string { + var b strings.Builder + b.WriteByte('(') + for i, t := range types { + if i != 0 { + b.WriteString(", ") + } + b.WriteString(t.String()) + } + b.WriteByte(')') + return b.String() +} + +// FixedWidthDataType is the representation of an Arrow type that +// requires a fixed number of bits in memory for each element. +type FixedWidthDataType interface { + DataType + // BitWidth returns the number of bits required to store a single element of this data type in memory. + BitWidth() int + // Bytes returns the number of bytes required to store a single element of this data type in memory. + Bytes() int +} + +type BinaryDataType interface { + DataType + IsUtf8() bool + binary() +} + +type OffsetsDataType interface { + DataType + OffsetTypeTraits() OffsetTraits +} + +func HashType(seed maphash.Seed, dt DataType) uint64 { + var h maphash.Hash + h.SetSeed(seed) + h.WriteString(dt.Fingerprint()) + return h.Sum64() +} + +func typeIDFingerprint(id Type) string { + c := string(rune(int(id) + int('A'))) + return "@" + c +} + +func typeFingerprint(typ DataType) string { return typeIDFingerprint(typ.ID()) } + +func timeUnitFingerprint(unit TimeUnit) rune { + switch unit { + case Second: + return 's' + case Millisecond: + return 'm' + case Microsecond: + return 'u' + case Nanosecond: + return 'n' + default: + debug.Assert(false, "unexpected time unit") + return rune(0) + } +} + +// BufferKind describes the type of buffer expected when defining a layout specification +type BufferKind int8 + +// The expected types of buffers +const ( + KindFixedWidth BufferKind = iota + KindVarWidth + KindBitmap + KindAlwaysNull +) + +// BufferSpec provides a specification for the buffers of a particular datatype +type BufferSpec struct { + Kind BufferKind + ByteWidth int // for KindFixedWidth +} + +func (b BufferSpec) Equals(other BufferSpec) bool { + return b.Kind == other.Kind && (b.Kind != KindFixedWidth || b.ByteWidth == other.ByteWidth) +} + +// DataTypeLayout represents the physical layout of a datatype's buffers including +// the number of and types of those binary buffers. This will correspond +// with the buffers in the ArrayData for an array of that type. +type DataTypeLayout struct { + Buffers []BufferSpec + HasDict bool +} + +func SpecFixedWidth(w int) BufferSpec { return BufferSpec{KindFixedWidth, w} } +func SpecVariableWidth() BufferSpec { return BufferSpec{KindVarWidth, -1} } +func SpecBitmap() BufferSpec { return BufferSpec{KindBitmap, -1} } +func SpecAlwaysNull() BufferSpec { return BufferSpec{KindAlwaysNull, -1} } + +// IsInteger is a helper to return true if the type ID provided is one of the +// integral types of uint or int with the varying sizes. +func IsInteger(t Type) bool { + switch t { + case UINT8, INT8, UINT16, INT16, UINT32, INT32, UINT64, INT64: + return true + } + return false +} + +// IsUnsignedInteger is a helper that returns true if the type ID provided is +// one of the uint integral types (uint8, uint16, uint32, uint64) +func IsUnsignedInteger(t Type) bool { + switch t { + case UINT8, UINT16, UINT32, UINT64: + return true + } + return false +} + +// IsSignedInteger is a helper that returns true if the type ID provided is +// one of the int integral types (int8, int16, int32, int64) +func IsSignedInteger(t Type) bool { + switch t { + case INT8, INT16, INT32, INT64: + return true + } + return false +} + +// IsFloating is a helper that returns true if the type ID provided is +// one of Float16, Float32, or Float64 +func IsFloating(t Type) bool { + switch t { + case FLOAT16, FLOAT32, FLOAT64: + return true + } + return false +} + +// IsPrimitive returns true if the provided type ID represents a fixed width +// primitive type. +func IsPrimitive(t Type) bool { + switch t { + case BOOL, UINT8, INT8, UINT16, INT16, UINT32, INT32, UINT64, INT64, + FLOAT16, FLOAT32, FLOAT64, DATE32, DATE64, TIME32, TIME64, TIMESTAMP, + DURATION, INTERVAL_MONTHS, INTERVAL_DAY_TIME, INTERVAL_MONTH_DAY_NANO: + return true + } + return false +} + +// IsBaseBinary returns true for Binary/String and their LARGE variants +func IsBaseBinary(t Type) bool { + switch t { + case BINARY, STRING, LARGE_BINARY, LARGE_STRING: + return true + } + return false +} + +// IsBinaryLike returns true for only BINARY and STRING +func IsBinaryLike(t Type) bool { + switch t { + case BINARY, STRING: + return true + } + return false +} + +// IsLargeBinaryLike returns true for only LARGE_BINARY and LARGE_STRING +func IsLargeBinaryLike(t Type) bool { + switch t { + case LARGE_BINARY, LARGE_STRING: + return true + } + return false +} + +// IsFixedSizeBinary returns true for Decimal128/256 and FixedSizeBinary +func IsFixedSizeBinary(t Type) bool { + switch t { + case DECIMAL128, DECIMAL256, FIXED_SIZE_BINARY: + return true + } + return false +} + +// IsDecimal returns true for Decimal128 and Decimal256 +func IsDecimal(t Type) bool { + switch t { + case DECIMAL128, DECIMAL256: + return true + } + return false +} + +// IsUnion returns true for Sparse and Dense Unions +func IsUnion(t Type) bool { + switch t { + case DENSE_UNION, SPARSE_UNION: + return true + } + return false +} + +// IsListLike returns true for List, LargeList, FixedSizeList, and Map +func IsListLike(t Type) bool { + switch t { + case LIST, LARGE_LIST, FIXED_SIZE_LIST, MAP: + return true + } + return false +} + +// IsNested returns true for List, LargeList, FixedSizeList, Map, Struct, and Unions +func IsNested(t Type) bool { + switch t { + case LIST, LARGE_LIST, FIXED_SIZE_LIST, MAP, LIST_VIEW, LARGE_LIST_VIEW, STRUCT, SPARSE_UNION, DENSE_UNION: + return true + } + return false +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/datatype_binary.go b/vendor/github.com/apache/arrow/go/v14/arrow/datatype_binary.go new file mode 100644 index 000000000..a3a856864 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/datatype_binary.go @@ -0,0 +1,98 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package arrow + +// OffsetTraits is a convenient interface over the various type traits +// constants such as arrow.Int32Traits allowing types with offsets, like +// BinaryType, StringType, LargeBinaryType and LargeStringType to have +// a method to return information about their offset type and how many bytes +// would be required to allocate an offset buffer for them. +type OffsetTraits interface { + // BytesRequired returns the number of bytes required to be allocated + // in order to hold the passed in number of elements of this type. + BytesRequired(int) int +} + +type BinaryType struct{} + +func (t *BinaryType) ID() Type { return BINARY } +func (t *BinaryType) Name() string { return "binary" } +func (t *BinaryType) String() string { return "binary" } +func (t *BinaryType) binary() {} +func (t *BinaryType) Fingerprint() string { return typeFingerprint(t) } +func (t *BinaryType) Layout() DataTypeLayout { + return DataTypeLayout{Buffers: []BufferSpec{SpecBitmap(), + SpecFixedWidth(Int32SizeBytes), SpecVariableWidth()}} +} +func (t *BinaryType) OffsetTypeTraits() OffsetTraits { return Int32Traits } +func (BinaryType) IsUtf8() bool { return false } + +type StringType struct{} + +func (t *StringType) ID() Type { return STRING } +func (t *StringType) Name() string { return "utf8" } +func (t *StringType) String() string { return "utf8" } +func (t *StringType) binary() {} +func (t *StringType) Fingerprint() string { return typeFingerprint(t) } +func (t *StringType) Layout() DataTypeLayout { + return DataTypeLayout{Buffers: []BufferSpec{SpecBitmap(), + SpecFixedWidth(Int32SizeBytes), SpecVariableWidth()}} +} +func (t *StringType) OffsetTypeTraits() OffsetTraits { return Int32Traits } +func (StringType) IsUtf8() bool { return true } + +type LargeBinaryType struct{} + +func (t *LargeBinaryType) ID() Type { return LARGE_BINARY } +func (t *LargeBinaryType) Name() string { return "large_binary" } +func (t *LargeBinaryType) String() string { return "large_binary" } +func (t *LargeBinaryType) binary() {} +func (t *LargeBinaryType) Fingerprint() string { return typeFingerprint(t) } +func (t *LargeBinaryType) Layout() DataTypeLayout { + return DataTypeLayout{Buffers: []BufferSpec{SpecBitmap(), + SpecFixedWidth(Int64SizeBytes), SpecVariableWidth()}} +} +func (t *LargeBinaryType) OffsetTypeTraits() OffsetTraits { return Int64Traits } +func (LargeBinaryType) IsUtf8() bool { return false } + +type LargeStringType struct{} + +func (t *LargeStringType) ID() Type { return LARGE_STRING } +func (t *LargeStringType) Name() string { return "large_utf8" } +func (t *LargeStringType) String() string { return "large_utf8" } +func (t *LargeStringType) binary() {} +func (t *LargeStringType) Fingerprint() string { return typeFingerprint(t) } +func (t *LargeStringType) Layout() DataTypeLayout { + return DataTypeLayout{Buffers: []BufferSpec{SpecBitmap(), + SpecFixedWidth(Int64SizeBytes), SpecVariableWidth()}} +} +func (t *LargeStringType) OffsetTypeTraits() OffsetTraits { return Int64Traits } +func (LargeStringType) IsUtf8() bool { return true } + +var ( + BinaryTypes = struct { + Binary BinaryDataType + String BinaryDataType + LargeBinary BinaryDataType + LargeString BinaryDataType + }{ + Binary: &BinaryType{}, + String: &StringType{}, + LargeBinary: &LargeBinaryType{}, + LargeString: &LargeStringType{}, + } +) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/datatype_encoded.go b/vendor/github.com/apache/arrow/go/v14/arrow/datatype_encoded.go new file mode 100644 index 000000000..c1750a889 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/datatype_encoded.go @@ -0,0 +1,67 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package arrow + +type EncodedType interface { + DataType + Encoded() DataType +} + +// RunEndEncodedType is the datatype to represent a run-end encoded +// array of data. ValueNullable defaults to true, but can be set false +// if this should represent a type with a non-nullable value field. +type RunEndEncodedType struct { + runEnds DataType + values DataType + ValueNullable bool +} + +func RunEndEncodedOf(runEnds, values DataType) *RunEndEncodedType { + return &RunEndEncodedType{runEnds: runEnds, values: values, ValueNullable: true} +} + +func (*RunEndEncodedType) ID() Type { return RUN_END_ENCODED } +func (*RunEndEncodedType) Name() string { return "run_end_encoded" } +func (*RunEndEncodedType) Layout() DataTypeLayout { + return DataTypeLayout{Buffers: []BufferSpec{SpecAlwaysNull()}} +} + +func (t *RunEndEncodedType) String() string { + return t.Name() + "" +} + +func (t *RunEndEncodedType) Fingerprint() string { + return typeFingerprint(t) + "{" + t.runEnds.Fingerprint() + ";" + t.values.Fingerprint() + ";}" +} + +func (t *RunEndEncodedType) RunEnds() DataType { return t.runEnds } +func (t *RunEndEncodedType) Encoded() DataType { return t.values } + +func (t *RunEndEncodedType) Fields() []Field { + return []Field{ + {Name: "run_ends", Type: t.runEnds}, + {Name: "values", Type: t.values, Nullable: t.ValueNullable}, + } +} + +func (*RunEndEncodedType) ValidRunEndsType(dt DataType) bool { + switch dt.ID() { + case INT16, INT32, INT64: + return true + } + return false +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/datatype_extension.go b/vendor/github.com/apache/arrow/go/v14/arrow/datatype_extension.go new file mode 100644 index 000000000..271c8b0db --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/datatype_extension.go @@ -0,0 +1,173 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package arrow + +import ( + "fmt" + "reflect" + "sync" +) + +var ( + // global extension type registry, initially left null to avoid paying + // the cost if no extension types are used. + // the choice to use a sync.Map here is because it's expected that most + // use cases would be to register some number of types at initialization + // or otherwise and leave them rather than a pattern of repeatedly registering + // and unregistering types. As per the documentation for sync.Map + // (https://pkg.go.dev/sync#Map), it is specialized for the case where an entry + // is written once but read many times which fits our case here as we register + // a type once and then have to read it many times when deserializing messages + // with that type. + extTypeRegistry *sync.Map + // used for initializing the registry once and only once + initReg sync.Once +) + +// convenience function to ensure that the type registry is initialized once +// and only once in a goroutine-safe manner. +func getExtTypeRegistry() *sync.Map { + initReg.Do(func() { extTypeRegistry = &sync.Map{} }) + return extTypeRegistry +} + +// RegisterExtensionType registers the provided ExtensionType by calling ExtensionName +// to use as a Key for registrying the type. If a type with the same name is already +// registered then this will return an error saying so, otherwise it will return nil +// if successful registering the type. +// This function is safe to call from multiple goroutines simultaneously. +func RegisterExtensionType(typ ExtensionType) error { + name := typ.ExtensionName() + registry := getExtTypeRegistry() + if _, existed := registry.LoadOrStore(name, typ); existed { + return fmt.Errorf("arrow: type extension with name %s already defined", name) + } + return nil +} + +// UnregisterExtensionType removes the type with the given name from the registry +// causing any messages with that type which come in to be expressed with their +// metadata and underlying type instead of the extension type that isn't known. +// This function is safe to call from multiple goroutines simultaneously. +func UnregisterExtensionType(typName string) error { + registry := getExtTypeRegistry() + if _, loaded := registry.LoadAndDelete(typName); !loaded { + return fmt.Errorf("arrow: no type extension with name %s found", typName) + } + return nil +} + +// GetExtensionType retrieves and returns the extension type of the given name +// from the global extension type registry. If the type isn't found it will return +// nil. This function is safe to call from multiple goroutines concurrently. +func GetExtensionType(typName string) ExtensionType { + registry := getExtTypeRegistry() + if val, ok := registry.Load(typName); ok { + return val.(ExtensionType) + } + return nil +} + +// ExtensionType is an interface for handling user-defined types. They must be +// DataTypes and must embed arrow.ExtensionBase in them in order to work properly +// ensuring that they always have the expected base behavior. +// +// The arrow.ExtensionBase that needs to be embedded implements the DataType interface +// leaving the remaining functions having to be implemented by the actual user-defined +// type in order to be handled properly. +type ExtensionType interface { + DataType + // ArrayType should return the reflect.TypeOf(ExtensionArrayType{}) where the + // ExtensionArrayType is a type that implements the array.ExtensionArray interface. + // Such a type must also embed the array.ExtensionArrayBase in it. This will be used + // when creating arrays of this ExtensionType by using reflect.New + ArrayType() reflect.Type + // ExtensionName is what will be used when registering / unregistering this extension + // type. Multiple user-defined types can be defined with a parameterized ExtensionType + // as long as the parameter is used in the ExtensionName to distinguish the instances + // in the global Extension Type registry. + // The return from this is also what will be placed in the metadata for IPC communication + // under the key ARROW:extension:name + ExtensionName() string + // StorageType returns the underlying storage type which is used by this extension + // type. It is already implemented by the ExtensionBase struct and thus does not need + // to be re-implemented by a user-defined type. + StorageType() DataType + // ExtensionEquals is used to tell whether two ExtensionType instances are equal types. + ExtensionEquals(ExtensionType) bool + // Serialize should produce any extra metadata necessary for initializing an instance of + // this user-defined type. Not all user-defined types require this and it is valid to return + // nil from this function or an empty slice. This is used for the IPC format and will be + // added to metadata for IPC communication under the key ARROW:extension:metadata + // This should be implemented such that it is valid to be called by multiple goroutines + // concurrently. + Serialize() string + // Deserialize is called when reading in extension arrays and types via the IPC format + // in order to construct an instance of the appropriate extension type. The data passed in + // is pulled from the ARROW:extension:metadata key and may be nil or an empty slice. + // If the storage type is incorrect or something else is invalid with the data this should + // return nil and an appropriate error. + Deserialize(storageType DataType, data string) (ExtensionType, error) + + mustEmbedExtensionBase() +} + +// ExtensionBase is the base struct for user-defined Extension Types which must be +// embedded in any user-defined types like so: +// +// type UserDefinedType struct { +// arrow.ExtensionBase +// // any other data +// } +type ExtensionBase struct { + // Storage is the underlying storage type + Storage DataType +} + +// ID always returns arrow.EXTENSION and should not be overridden +func (*ExtensionBase) ID() Type { return EXTENSION } + +// Name should always return "extension" and should not be overridden +func (*ExtensionBase) Name() string { return "extension" } + +// String by default will return "extension_type" by can be overridden +// to customize what is printed out when printing this extension type. +func (e *ExtensionBase) String() string { return fmt.Sprintf("extension_type", e.Storage) } + +// StorageType returns the underlying storage type and exists so that functions +// written against the ExtensionType interface can access the storage type. +func (e *ExtensionBase) StorageType() DataType { return e.Storage } + +func (e *ExtensionBase) Fingerprint() string { return typeFingerprint(e) + e.Storage.Fingerprint() } + +func (e *ExtensionBase) Fields() []Field { + if nested, ok := e.Storage.(NestedType); ok { + return nested.Fields() + } + return nil +} + +func (e *ExtensionBase) Layout() DataTypeLayout { return e.Storage.Layout() } + +// this no-op exists to ensure that this type must be embedded in any user-defined extension type. +// +//lint:ignore U1000 this function is intentionally unused as it only exists to ensure embedding happens +func (ExtensionBase) mustEmbedExtensionBase() {} + +var ( + _ DataType = (*ExtensionBase)(nil) +) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/datatype_fixedwidth.go b/vendor/github.com/apache/arrow/go/v14/arrow/datatype_fixedwidth.go new file mode 100644 index 000000000..fc0b3aea5 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/datatype_fixedwidth.go @@ -0,0 +1,819 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package arrow + +import ( + "fmt" + "strconv" + "time" + + "github.com/apache/arrow/go/v14/internal/json" + + "golang.org/x/xerrors" +) + +type BooleanType struct{} + +func (t *BooleanType) ID() Type { return BOOL } +func (t *BooleanType) Name() string { return "bool" } +func (t *BooleanType) String() string { return "bool" } +func (t *BooleanType) Fingerprint() string { return typeFingerprint(t) } +func (BooleanType) Bytes() int { return 1 } + +// BitWidth returns the number of bits required to store a single element of this data type in memory. +func (t *BooleanType) BitWidth() int { return 1 } + +func (BooleanType) Layout() DataTypeLayout { + return DataTypeLayout{Buffers: []BufferSpec{SpecBitmap(), SpecBitmap()}} +} + +type FixedSizeBinaryType struct { + ByteWidth int +} + +func (*FixedSizeBinaryType) ID() Type { return FIXED_SIZE_BINARY } +func (*FixedSizeBinaryType) Name() string { return "fixed_size_binary" } +func (t *FixedSizeBinaryType) BitWidth() int { return 8 * t.ByteWidth } +func (t *FixedSizeBinaryType) Bytes() int { return t.ByteWidth } +func (t *FixedSizeBinaryType) Fingerprint() string { return typeFingerprint(t) } +func (t *FixedSizeBinaryType) String() string { + return "fixed_size_binary[" + strconv.Itoa(t.ByteWidth) + "]" +} +func (t *FixedSizeBinaryType) Layout() DataTypeLayout { + return DataTypeLayout{Buffers: []BufferSpec{SpecBitmap(), SpecFixedWidth(t.ByteWidth)}} +} + +type ( + Timestamp int64 + Time32 int32 + Time64 int64 + TimeUnit int + Date32 int32 + Date64 int64 + Duration int64 +) + +// Date32FromTime returns a Date32 value from a time object +func Date32FromTime(t time.Time) Date32 { + if _, offset := t.Zone(); offset != 0 { + // properly account for timezone adjustments before we calculate + // the number of days by adjusting the time and converting to UTC + t = t.Add(time.Duration(offset) * time.Second).UTC() + } + return Date32(t.Truncate(24*time.Hour).Unix() / int64((time.Hour * 24).Seconds())) +} + +func (d Date32) ToTime() time.Time { + return time.Unix(0, 0).UTC().AddDate(0, 0, int(d)) +} + +func (d Date32) FormattedString() string { + return d.ToTime().Format("2006-01-02") +} + +// Date64FromTime returns a Date64 value from a time object +func Date64FromTime(t time.Time) Date64 { + if _, offset := t.Zone(); offset != 0 { + // properly account for timezone adjustments before we calculate + // the actual value by adjusting the time and converting to UTC + t = t.Add(time.Duration(offset) * time.Second).UTC() + } + // truncate to the start of the day to get the correct value + t = t.Truncate(24 * time.Hour) + return Date64(t.Unix()*1e3 + int64(t.Nanosecond())/1e6) +} + +func (d Date64) ToTime() time.Time { + days := int(int64(d) / (time.Hour * 24).Milliseconds()) + return time.Unix(0, 0).UTC().AddDate(0, 0, days) +} + +func (d Date64) FormattedString() string { + return d.ToTime().Format("2006-01-02") +} + +// TimestampFromStringInLocation is like TimestampFromString, but treats the time instant +// as if it were in the provided timezone before converting to UTC for internal representation. +func TimestampFromStringInLocation(val string, unit TimeUnit, loc *time.Location) (Timestamp, bool, error) { + if len(val) < 10 { + return 0, false, fmt.Errorf("%w: invalid timestamp string", ErrInvalid) + } + + var ( + format = "2006-01-02" + zoneFmt string + lenWithoutZone = len(val) + ) + + if lenWithoutZone > 10 { + switch { + case val[len(val)-1] == 'Z': + zoneFmt = "Z" + lenWithoutZone-- + case val[len(val)-3] == '+' || val[len(val)-3] == '-': + zoneFmt = "-07" + lenWithoutZone -= 3 + case val[len(val)-5] == '+' || val[len(val)-5] == '-': + zoneFmt = "-0700" + lenWithoutZone -= 5 + case val[len(val)-6] == '+' || val[len(val)-6] == '-': + zoneFmt = "-07:00" + lenWithoutZone -= 6 + } + } + + switch { + case lenWithoutZone == 13: + format += string(val[10]) + "15" + case lenWithoutZone == 16: + format += string(val[10]) + "15:04" + case lenWithoutZone >= 19: + format += string(val[10]) + "15:04:05.999999999" + } + + // error if we're truncating precision + // don't need a case for nano as time.Parse will already error if + // more than nanosecond precision is provided + switch { + case unit == Second && lenWithoutZone > 19: + return 0, zoneFmt != "", xerrors.New("provided more than second precision for timestamp[s]") + case unit == Millisecond && lenWithoutZone > 23: + return 0, zoneFmt != "", xerrors.New("provided more than millisecond precision for timestamp[ms]") + case unit == Microsecond && lenWithoutZone > 26: + return 0, zoneFmt != "", xerrors.New("provided more than microsecond precision for timestamp[us]") + } + + format += zoneFmt + out, err := time.Parse(format, val) + if err != nil { + return 0, zoneFmt != "", fmt.Errorf("%w: %s", ErrInvalid, err) + } + if loc != time.UTC { + // convert to UTC by putting the same time instant in the desired location + // before converting to UTC + out = out.In(loc).UTC() + } + + ts, err := TimestampFromTime(out, unit) + return ts, zoneFmt != "", err +} + +// TimestampFromString parses a string and returns a timestamp for the given unit +// level. +// +// The timestamp should be in one of the following forms, [T] can be either T +// or a space, and [.zzzzzzzzz] can be either left out or up to 9 digits of +// fractions of a second. +// +// YYYY-MM-DD +// YYYY-MM-DD[T]HH +// YYYY-MM-DD[T]HH:MM +// YYYY-MM-DD[T]HH:MM:SS[.zzzzzzzz] +// +// You can also optionally have an ending Z to indicate UTC or indicate a specific +// timezone using ±HH, ±HHMM or ±HH:MM at the end of the string. +func TimestampFromString(val string, unit TimeUnit) (Timestamp, error) { + tm, _, err := TimestampFromStringInLocation(val, unit, time.UTC) + return tm, err +} + +func (t Timestamp) ToTime(unit TimeUnit) time.Time { + switch unit { + case Second: + return time.Unix(int64(t), 0).UTC() + case Millisecond: + return time.UnixMilli(int64(t)).UTC() + case Microsecond: + return time.UnixMicro(int64(t)).UTC() + default: + return time.Unix(0, int64(t)).UTC() + } +} + +// TimestampFromTime allows converting time.Time to Timestamp +func TimestampFromTime(val time.Time, unit TimeUnit) (Timestamp, error) { + switch unit { + case Second: + return Timestamp(val.Unix()), nil + case Millisecond: + return Timestamp(val.Unix()*1e3 + int64(val.Nanosecond())/1e6), nil + case Microsecond: + return Timestamp(val.Unix()*1e6 + int64(val.Nanosecond())/1e3), nil + case Nanosecond: + return Timestamp(val.UnixNano()), nil + default: + return 0, fmt.Errorf("%w: unexpected timestamp unit: %s", ErrInvalid, unit) + } +} + +// Time32FromString parses a string to return a Time32 value in the given unit, +// unit needs to be only seconds or milliseconds and the string should be in the +// form of HH:MM or HH:MM:SS[.zzz] where the fractions of a second are optional. +func Time32FromString(val string, unit TimeUnit) (Time32, error) { + switch unit { + case Second: + if len(val) > 8 { + return 0, xerrors.New("cannot convert larger than second precision to time32s") + } + case Millisecond: + if len(val) > 12 { + return 0, xerrors.New("cannot convert larger than millisecond precision to time32ms") + } + case Microsecond, Nanosecond: + return 0, xerrors.New("time32 can only be seconds or milliseconds") + } + + var ( + out time.Time + err error + ) + switch { + case len(val) == 5: + out, err = time.Parse("15:04", val) + default: + out, err = time.Parse("15:04:05.999", val) + } + if err != nil { + return 0, err + } + t := out.Sub(time.Date(0, 1, 1, 0, 0, 0, 0, time.UTC)) + if unit == Second { + return Time32(t.Seconds()), nil + } + return Time32(t.Milliseconds()), nil +} + +func (t Time32) ToTime(unit TimeUnit) time.Time { + return time.Unix(0, int64(t)*int64(unit.Multiplier())).UTC() +} + +func (t Time32) FormattedString(unit TimeUnit) string { + const baseFmt = "15:04:05" + tm := t.ToTime(unit) + switch unit { + case Second: + return tm.Format(baseFmt) + case Millisecond: + return tm.Format(baseFmt + ".000") + } + return "" +} + +// Time64FromString parses a string to return a Time64 value in the given unit, +// unit needs to be only microseconds or nanoseconds and the string should be in the +// form of HH:MM or HH:MM:SS[.zzzzzzzzz] where the fractions of a second are optional. +func Time64FromString(val string, unit TimeUnit) (Time64, error) { + // don't need to check length for nanoseconds as Parse will already error + // if more than 9 digits are provided for the fractional second + switch unit { + case Microsecond: + if len(val) > 15 { + return 0, xerrors.New("cannot convert larger than microsecond precision to time64us") + } + case Second, Millisecond: + return 0, xerrors.New("time64 should only be microseconds or nanoseconds") + } + + var ( + out time.Time + err error + ) + switch { + case len(val) == 5: + out, err = time.Parse("15:04", val) + default: + out, err = time.Parse("15:04:05.999999999", val) + } + if err != nil { + return 0, err + } + t := out.Sub(time.Date(0, 1, 1, 0, 0, 0, 0, time.UTC)) + if unit == Microsecond { + return Time64(t.Microseconds()), nil + } + return Time64(t.Nanoseconds()), nil +} + +func (t Time64) ToTime(unit TimeUnit) time.Time { + return time.Unix(0, int64(t)*int64(unit.Multiplier())).UTC() +} + +func (t Time64) FormattedString(unit TimeUnit) string { + const baseFmt = "15:04:05.000000" + tm := t.ToTime(unit) + switch unit { + case Microsecond: + return tm.Format(baseFmt) + case Nanosecond: + return tm.Format(baseFmt + "000") + } + return "" +} + +const ( + Second TimeUnit = iota + Millisecond + Microsecond + Nanosecond +) + +var TimeUnitValues = []TimeUnit{Second, Millisecond, Microsecond, Nanosecond} + +// Multiplier returns a time.Duration value to multiply by in order to +// convert the value into nanoseconds +func (u TimeUnit) Multiplier() time.Duration { + return [...]time.Duration{time.Second, time.Millisecond, time.Microsecond, time.Nanosecond}[uint(u)&3] +} + +func (u TimeUnit) String() string { return [...]string{"s", "ms", "us", "ns"}[uint(u)&3] } + +type TemporalWithUnit interface { + FixedWidthDataType + TimeUnit() TimeUnit +} + +// TimestampType is encoded as a 64-bit signed integer since the UNIX epoch (2017-01-01T00:00:00Z). +// The zero-value is a second and time zone neutral. Time zone neutral can be +// considered UTC without having "UTC" as a time zone. +type TimestampType struct { + Unit TimeUnit + TimeZone string + + loc *time.Location +} + +func (*TimestampType) ID() Type { return TIMESTAMP } +func (*TimestampType) Name() string { return "timestamp" } +func (t *TimestampType) String() string { + switch len(t.TimeZone) { + case 0: + return "timestamp[" + t.Unit.String() + "]" + default: + return "timestamp[" + t.Unit.String() + ", tz=" + t.TimeZone + "]" + } +} + +func (t *TimestampType) Fingerprint() string { + return fmt.Sprintf("%s%d:%s", typeFingerprint(t)+string(timeUnitFingerprint(t.Unit)), len(t.TimeZone), t.TimeZone) +} + +// BitWidth returns the number of bits required to store a single element of this data type in memory. +func (*TimestampType) BitWidth() int { return 64 } + +func (*TimestampType) Bytes() int { return Int64SizeBytes } + +func (*TimestampType) Layout() DataTypeLayout { + return DataTypeLayout{Buffers: []BufferSpec{SpecBitmap(), SpecFixedWidth(TimestampSizeBytes)}} +} + +func (t *TimestampType) TimeUnit() TimeUnit { return t.Unit } + +// ClearCachedLocation clears the cached time.Location object in the type. +// This should be called if you change the value of the TimeZone after having +// potentially called GetZone. +func (t *TimestampType) ClearCachedLocation() { + t.loc = nil +} + +// GetZone returns a *time.Location that represents the current TimeZone member +// of the TimestampType. If it is "", "UTC", or "utc", you'll get time.UTC. +// Otherwise it must either be a valid tzdata string such as "America/New_York" +// or of the format +HH:MM or -HH:MM indicating an absolute offset. +// +// The location object will be cached in the TimestampType for subsequent calls +// so if you change the value of TimeZone after calling this, make sure to call +// ClearCachedLocation. +func (t *TimestampType) GetZone() (*time.Location, error) { + if t.loc != nil { + return t.loc, nil + } + + // the TimeZone string is allowed to be either a valid tzdata string + // such as "America/New_York" or an absolute offset of the form -XX:XX + // or +XX:XX + // + // As such we have two methods we can try, first we'll try LoadLocation + // and if that fails, we'll test for an absolute offset. + if t.TimeZone == "" || t.TimeZone == "UTC" || t.TimeZone == "utc" { + t.loc = time.UTC + return time.UTC, nil + } + + if loc, err := time.LoadLocation(t.TimeZone); err == nil { + t.loc = loc + return t.loc, err + } + + // at this point we know that the timezone isn't empty, and didn't match + // anything in the tzdata names. So either it's an absolute offset + // or it's invalid. + timetz, err := time.Parse("-07:00", t.TimeZone) + if err != nil { + return time.UTC, fmt.Errorf("could not find timezone location for '%s'", t.TimeZone) + } + + _, offset := timetz.Zone() + t.loc = time.FixedZone(t.TimeZone, offset) + return t.loc, nil +} + +// GetToTimeFunc returns a function for converting an arrow.Timestamp value into a +// time.Time object with proper TimeZone and precision. If the TimeZone is invalid +// this will return an error. It calls GetZone to get the timezone for consistency. +func (t *TimestampType) GetToTimeFunc() (func(Timestamp) time.Time, error) { + tz, err := t.GetZone() + if err != nil { + return nil, err + } + + switch t.Unit { + case Second: + return func(v Timestamp) time.Time { return time.Unix(int64(v), 0).In(tz) }, nil + case Millisecond: + return func(v Timestamp) time.Time { return time.UnixMilli(int64(v)).In(tz) }, nil + case Microsecond: + return func(v Timestamp) time.Time { return time.UnixMicro(int64(v)).In(tz) }, nil + case Nanosecond: + return func(v Timestamp) time.Time { return time.Unix(0, int64(v)).In(tz) }, nil + } + return nil, fmt.Errorf("invalid timestamp unit: %s", t.Unit) +} + +// Time32Type is encoded as a 32-bit signed integer, representing either seconds or milliseconds since midnight. +type Time32Type struct { + Unit TimeUnit +} + +func (*Time32Type) ID() Type { return TIME32 } +func (*Time32Type) Name() string { return "time32" } +func (*Time32Type) BitWidth() int { return 32 } +func (*Time32Type) Bytes() int { return Int32SizeBytes } +func (t *Time32Type) String() string { return "time32[" + t.Unit.String() + "]" } +func (t *Time32Type) Fingerprint() string { + return typeFingerprint(t) + string(timeUnitFingerprint(t.Unit)) +} + +func (Time32Type) Layout() DataTypeLayout { + return DataTypeLayout{Buffers: []BufferSpec{SpecBitmap(), SpecFixedWidth(Time32SizeBytes)}} +} + +func (t *Time32Type) TimeUnit() TimeUnit { return t.Unit } + +// Time64Type is encoded as a 64-bit signed integer, representing either microseconds or nanoseconds since midnight. +type Time64Type struct { + Unit TimeUnit +} + +func (*Time64Type) ID() Type { return TIME64 } +func (*Time64Type) Name() string { return "time64" } +func (*Time64Type) BitWidth() int { return 64 } +func (*Time64Type) Bytes() int { return Int64SizeBytes } +func (t *Time64Type) String() string { return "time64[" + t.Unit.String() + "]" } +func (t *Time64Type) Fingerprint() string { + return typeFingerprint(t) + string(timeUnitFingerprint(t.Unit)) +} + +func (Time64Type) Layout() DataTypeLayout { + return DataTypeLayout{Buffers: []BufferSpec{SpecBitmap(), SpecFixedWidth(Time64SizeBytes)}} +} + +func (t *Time64Type) TimeUnit() TimeUnit { return t.Unit } + +// DurationType is encoded as a 64-bit signed integer, representing an amount +// of elapsed time without any relation to a calendar artifact. +type DurationType struct { + Unit TimeUnit +} + +func (*DurationType) ID() Type { return DURATION } +func (*DurationType) Name() string { return "duration" } +func (*DurationType) BitWidth() int { return 64 } +func (*DurationType) Bytes() int { return Int64SizeBytes } +func (t *DurationType) String() string { return "duration[" + t.Unit.String() + "]" } +func (t *DurationType) Fingerprint() string { + return typeFingerprint(t) + string(timeUnitFingerprint(t.Unit)) +} + +func (DurationType) Layout() DataTypeLayout { + return DataTypeLayout{Buffers: []BufferSpec{SpecBitmap(), SpecFixedWidth(DurationSizeBytes)}} +} + +func (t *DurationType) TimeUnit() TimeUnit { return t.Unit } + +// Float16Type represents a floating point value encoded with a 16-bit precision. +type Float16Type struct{} + +func (t *Float16Type) ID() Type { return FLOAT16 } +func (t *Float16Type) Name() string { return "float16" } +func (t *Float16Type) String() string { return "float16" } +func (t *Float16Type) Fingerprint() string { return typeFingerprint(t) } + +// BitWidth returns the number of bits required to store a single element of this data type in memory. +func (t *Float16Type) BitWidth() int { return 16 } + +func (Float16Type) Bytes() int { return Float16SizeBytes } + +func (Float16Type) Layout() DataTypeLayout { + return DataTypeLayout{Buffers: []BufferSpec{SpecBitmap(), SpecFixedWidth(Float16SizeBytes)}} +} + +type DecimalType interface { + DataType + GetPrecision() int32 + GetScale() int32 +} + +func NewDecimalType(id Type, prec, scale int32) (DecimalType, error) { + switch id { + case DECIMAL128: + return &Decimal128Type{Precision: prec, Scale: scale}, nil + case DECIMAL256: + return &Decimal256Type{Precision: prec, Scale: scale}, nil + default: + return nil, fmt.Errorf("%w: must use DECIMAL128 or DECIMAL256 to create a DecimalType", ErrInvalid) + } +} + +// Decimal128Type represents a fixed-size 128-bit decimal type. +type Decimal128Type struct { + Precision int32 + Scale int32 +} + +func (*Decimal128Type) ID() Type { return DECIMAL128 } +func (*Decimal128Type) Name() string { return "decimal" } +func (*Decimal128Type) BitWidth() int { return 128 } +func (*Decimal128Type) Bytes() int { return Decimal128SizeBytes } +func (t *Decimal128Type) String() string { + return fmt.Sprintf("%s(%d, %d)", t.Name(), t.Precision, t.Scale) +} +func (t *Decimal128Type) Fingerprint() string { + return fmt.Sprintf("%s[%d,%d,%d]", typeFingerprint(t), t.BitWidth(), t.Precision, t.Scale) +} +func (t *Decimal128Type) GetPrecision() int32 { return t.Precision } +func (t *Decimal128Type) GetScale() int32 { return t.Scale } + +func (Decimal128Type) Layout() DataTypeLayout { + return DataTypeLayout{Buffers: []BufferSpec{SpecBitmap(), SpecFixedWidth(Decimal128SizeBytes)}} +} + +// Decimal256Type represents a fixed-size 256-bit decimal type. +type Decimal256Type struct { + Precision int32 + Scale int32 +} + +func (*Decimal256Type) ID() Type { return DECIMAL256 } +func (*Decimal256Type) Name() string { return "decimal256" } +func (*Decimal256Type) BitWidth() int { return 256 } +func (*Decimal256Type) Bytes() int { return Decimal256SizeBytes } +func (t *Decimal256Type) String() string { + return fmt.Sprintf("%s(%d, %d)", t.Name(), t.Precision, t.Scale) +} +func (t *Decimal256Type) Fingerprint() string { + return fmt.Sprintf("%s[%d,%d,%d]", typeFingerprint(t), t.BitWidth(), t.Precision, t.Scale) +} +func (t *Decimal256Type) GetPrecision() int32 { return t.Precision } +func (t *Decimal256Type) GetScale() int32 { return t.Scale } + +func (Decimal256Type) Layout() DataTypeLayout { + return DataTypeLayout{Buffers: []BufferSpec{SpecBitmap(), SpecFixedWidth(Decimal256SizeBytes)}} +} + +// MonthInterval represents a number of months. +type MonthInterval int32 + +func (m *MonthInterval) UnmarshalJSON(data []byte) error { + var val struct { + Months int32 `json:"months"` + } + if err := json.Unmarshal(data, &val); err != nil { + return err + } + + *m = MonthInterval(val.Months) + return nil +} + +func (m MonthInterval) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Months int32 `json:"months"` + }{int32(m)}) +} + +// MonthIntervalType is encoded as a 32-bit signed integer, +// representing a number of months. +type MonthIntervalType struct{} + +func (*MonthIntervalType) ID() Type { return INTERVAL_MONTHS } +func (*MonthIntervalType) Name() string { return "month_interval" } +func (*MonthIntervalType) String() string { return "month_interval" } +func (*MonthIntervalType) Fingerprint() string { return typeIDFingerprint(INTERVAL_MONTHS) + "M" } + +// BitWidth returns the number of bits required to store a single element of this data type in memory. +func (t *MonthIntervalType) BitWidth() int { return 32 } + +func (MonthIntervalType) Bytes() int { return Int32SizeBytes } +func (MonthIntervalType) Layout() DataTypeLayout { + return DataTypeLayout{Buffers: []BufferSpec{SpecBitmap(), SpecFixedWidth(MonthIntervalSizeBytes)}} +} + +// DayTimeInterval represents a number of days and milliseconds (fraction of day). +type DayTimeInterval struct { + Days int32 `json:"days"` + Milliseconds int32 `json:"milliseconds"` +} + +// DayTimeIntervalType is encoded as a pair of 32-bit signed integer, +// representing a number of days and milliseconds (fraction of day). +type DayTimeIntervalType struct{} + +func (*DayTimeIntervalType) ID() Type { return INTERVAL_DAY_TIME } +func (*DayTimeIntervalType) Name() string { return "day_time_interval" } +func (*DayTimeIntervalType) String() string { return "day_time_interval" } +func (*DayTimeIntervalType) Fingerprint() string { return typeIDFingerprint(INTERVAL_DAY_TIME) + "d" } + +// BitWidth returns the number of bits required to store a single element of this data type in memory. +func (t *DayTimeIntervalType) BitWidth() int { return 64 } + +func (DayTimeIntervalType) Bytes() int { return DayTimeIntervalSizeBytes } +func (DayTimeIntervalType) Layout() DataTypeLayout { + return DataTypeLayout{Buffers: []BufferSpec{SpecBitmap(), SpecFixedWidth(DayTimeIntervalSizeBytes)}} +} + +// MonthDayNanoInterval represents a number of months, days and nanoseconds (fraction of day). +type MonthDayNanoInterval struct { + Months int32 `json:"months"` + Days int32 `json:"days"` + Nanoseconds int64 `json:"nanoseconds"` +} + +// MonthDayNanoIntervalType is encoded as two signed 32-bit integers representing +// a number of months and a number of days, followed by a 64-bit integer representing +// the number of nanoseconds since midnight for fractions of a day. +type MonthDayNanoIntervalType struct{} + +func (*MonthDayNanoIntervalType) ID() Type { return INTERVAL_MONTH_DAY_NANO } +func (*MonthDayNanoIntervalType) Name() string { return "month_day_nano_interval" } +func (*MonthDayNanoIntervalType) String() string { return "month_day_nano_interval" } +func (*MonthDayNanoIntervalType) Fingerprint() string { + return typeIDFingerprint(INTERVAL_MONTH_DAY_NANO) + "N" +} + +// BitWidth returns the number of bits required to store a single element of this data type in memory. +func (*MonthDayNanoIntervalType) BitWidth() int { return 128 } +func (*MonthDayNanoIntervalType) Bytes() int { return MonthDayNanoIntervalSizeBytes } +func (MonthDayNanoIntervalType) Layout() DataTypeLayout { + return DataTypeLayout{Buffers: []BufferSpec{SpecBitmap(), SpecFixedWidth(MonthDayNanoIntervalSizeBytes)}} +} + +type TimestampConvertOp int8 + +const ( + ConvDIVIDE = iota + ConvMULTIPLY +) + +var timestampConversion = [...][4]struct { + op TimestampConvertOp + factor int64 +}{ + Nanosecond: { + Nanosecond: {ConvMULTIPLY, int64(time.Nanosecond)}, + Microsecond: {ConvDIVIDE, int64(time.Microsecond)}, + Millisecond: {ConvDIVIDE, int64(time.Millisecond)}, + Second: {ConvDIVIDE, int64(time.Second)}, + }, + Microsecond: { + Nanosecond: {ConvMULTIPLY, int64(time.Microsecond)}, + Microsecond: {ConvMULTIPLY, 1}, + Millisecond: {ConvDIVIDE, int64(time.Millisecond / time.Microsecond)}, + Second: {ConvDIVIDE, int64(time.Second / time.Microsecond)}, + }, + Millisecond: { + Nanosecond: {ConvMULTIPLY, int64(time.Millisecond)}, + Microsecond: {ConvMULTIPLY, int64(time.Millisecond / time.Microsecond)}, + Millisecond: {ConvMULTIPLY, 1}, + Second: {ConvDIVIDE, int64(time.Second / time.Millisecond)}, + }, + Second: { + Nanosecond: {ConvMULTIPLY, int64(time.Second)}, + Microsecond: {ConvMULTIPLY, int64(time.Second / time.Microsecond)}, + Millisecond: {ConvMULTIPLY, int64(time.Second / time.Millisecond)}, + Second: {ConvMULTIPLY, 1}, + }, +} + +func GetTimestampConvert(in, out TimeUnit) (op TimestampConvertOp, factor int64) { + conv := timestampConversion[int(in)][int(out)] + return conv.op, conv.factor +} + +func ConvertTimestampValue(in, out TimeUnit, value int64) int64 { + conv := timestampConversion[int(in)][int(out)] + switch conv.op { + case ConvMULTIPLY: + return value * conv.factor + case ConvDIVIDE: + return value / conv.factor + } + + return 0 +} + +// DictionaryType represents categorical or dictionary-encoded in-memory data +// It contains a dictionary-encoded value type (any type) and an index type +// (any integer type). +type DictionaryType struct { + IndexType DataType + ValueType DataType + Ordered bool +} + +func (*DictionaryType) ID() Type { return DICTIONARY } +func (*DictionaryType) Name() string { return "dictionary" } +func (d *DictionaryType) BitWidth() int { return d.IndexType.(FixedWidthDataType).BitWidth() } +func (d *DictionaryType) Bytes() int { return d.IndexType.(FixedWidthDataType).Bytes() } +func (d *DictionaryType) String() string { + return fmt.Sprintf("%s", + d.Name(), d.ValueType, d.IndexType, d.Ordered) +} +func (d *DictionaryType) Fingerprint() string { + indexFingerprint := d.IndexType.Fingerprint() + valueFingerprint := d.ValueType.Fingerprint() + ordered := "1" + if !d.Ordered { + ordered = "0" + } + + if len(valueFingerprint) > 0 { + return typeFingerprint(d) + indexFingerprint + valueFingerprint + ordered + } + return ordered +} + +func (d *DictionaryType) Layout() DataTypeLayout { + layout := d.IndexType.Layout() + layout.HasDict = true + return layout +} + +var ( + FixedWidthTypes = struct { + Boolean FixedWidthDataType + Date32 FixedWidthDataType + Date64 FixedWidthDataType + DayTimeInterval FixedWidthDataType + Duration_s FixedWidthDataType + Duration_ms FixedWidthDataType + Duration_us FixedWidthDataType + Duration_ns FixedWidthDataType + Float16 FixedWidthDataType + MonthInterval FixedWidthDataType + Time32s FixedWidthDataType + Time32ms FixedWidthDataType + Time64us FixedWidthDataType + Time64ns FixedWidthDataType + Timestamp_s FixedWidthDataType + Timestamp_ms FixedWidthDataType + Timestamp_us FixedWidthDataType + Timestamp_ns FixedWidthDataType + MonthDayNanoInterval FixedWidthDataType + }{ + Boolean: &BooleanType{}, + Date32: &Date32Type{}, + Date64: &Date64Type{}, + DayTimeInterval: &DayTimeIntervalType{}, + Duration_s: &DurationType{Unit: Second}, + Duration_ms: &DurationType{Unit: Millisecond}, + Duration_us: &DurationType{Unit: Microsecond}, + Duration_ns: &DurationType{Unit: Nanosecond}, + Float16: &Float16Type{}, + MonthInterval: &MonthIntervalType{}, + Time32s: &Time32Type{Unit: Second}, + Time32ms: &Time32Type{Unit: Millisecond}, + Time64us: &Time64Type{Unit: Microsecond}, + Time64ns: &Time64Type{Unit: Nanosecond}, + Timestamp_s: &TimestampType{Unit: Second, TimeZone: "UTC"}, + Timestamp_ms: &TimestampType{Unit: Millisecond, TimeZone: "UTC"}, + Timestamp_us: &TimestampType{Unit: Microsecond, TimeZone: "UTC"}, + Timestamp_ns: &TimestampType{Unit: Nanosecond, TimeZone: "UTC"}, + MonthDayNanoInterval: &MonthDayNanoIntervalType{}, + } + + _ FixedWidthDataType = (*FixedSizeBinaryType)(nil) +) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/datatype_nested.go b/vendor/github.com/apache/arrow/go/v14/arrow/datatype_nested.go new file mode 100644 index 000000000..4ae488033 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/datatype_nested.go @@ -0,0 +1,977 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package arrow + +import ( + "errors" + "fmt" + "strconv" + "strings" + + "github.com/apache/arrow/go/v14/arrow/internal/debug" +) + +type ( + NestedType interface { + DataType + + // Fields method provides a copy of NestedType fields + // (so it can be safely mutated and will not result in updating the NestedType). + Fields() []Field + } + + ListLikeType interface { + DataType + Elem() DataType + ElemField() Field + } + + VarLenListLikeType interface { + ListLikeType + } +) + +// ListType describes a nested type in which each array slot contains +// a variable-size sequence of values, all having the same relative type. +type ListType struct { + elem Field +} + +func ListOfField(f Field) *ListType { + if f.Type == nil { + panic("arrow: nil type for list field") + } + return &ListType{elem: f} +} + +// ListOf returns the list type with element type t. +// For example, if t represents int32, ListOf(t) represents []int32. +// +// ListOf panics if t is nil or invalid. NullableElem defaults to true +func ListOf(t DataType) *ListType { + if t == nil { + panic("arrow: nil DataType") + } + return &ListType{elem: Field{Name: "item", Type: t, Nullable: true}} +} + +// ListOfNonNullable is like ListOf but NullableElem defaults to false, indicating +// that the child type should be marked as non-nullable. +func ListOfNonNullable(t DataType) *ListType { + if t == nil { + panic("arrow: nil DataType") + } + return &ListType{elem: Field{Name: "item", Type: t, Nullable: false}} +} + +func (*ListType) ID() Type { return LIST } +func (*ListType) Name() string { return "list" } + +func (t *ListType) String() string { + if t.elem.Nullable { + return fmt.Sprintf("list<%s: %s, nullable>", t.elem.Name, t.elem.Type) + } + return fmt.Sprintf("list<%s: %s>", t.elem.Name, t.elem.Type) +} + +func (t *ListType) Fingerprint() string { + child := t.elem.Type.Fingerprint() + if len(child) > 0 { + return typeFingerprint(t) + "{" + child + "}" + } + return "" +} + +func (t *ListType) SetElemMetadata(md Metadata) { t.elem.Metadata = md } + +func (t *ListType) SetElemNullable(n bool) { t.elem.Nullable = n } + +// Elem returns the ListType's element type. +func (t *ListType) Elem() DataType { return t.elem.Type } + +func (t *ListType) ElemField() Field { + return t.elem +} + +func (t *ListType) Fields() []Field { return []Field{t.ElemField()} } + +func (*ListType) Layout() DataTypeLayout { + return DataTypeLayout{Buffers: []BufferSpec{SpecBitmap(), SpecFixedWidth(Int32SizeBytes)}} +} + +func (*ListType) OffsetTypeTraits() OffsetTraits { return Int32Traits } + +type LargeListType struct { + ListType +} + +func (LargeListType) ID() Type { return LARGE_LIST } +func (LargeListType) Name() string { return "large_list" } +func (t *LargeListType) String() string { + return "large_" + t.ListType.String() +} + +func (t *LargeListType) Fingerprint() string { + child := t.elem.Type.Fingerprint() + if len(child) > 0 { + return typeFingerprint(t) + "{" + child + "}" + } + return "" +} + +func (*LargeListType) Layout() DataTypeLayout { + return DataTypeLayout{Buffers: []BufferSpec{SpecBitmap(), SpecFixedWidth(Int64SizeBytes)}} +} + +func (*LargeListType) OffsetTypeTraits() OffsetTraits { return Int64Traits } + +func LargeListOfField(f Field) *LargeListType { + if f.Type == nil { + panic("arrow: nil type for list field") + } + return &LargeListType{ListType{elem: f}} +} + +// LargeListOf returns the list type with element type t. +// For example, if t represents int32, LargeListOf(t) represents []int32. +// +// LargeListOf panics if t is nil or invalid. NullableElem defaults to true +func LargeListOf(t DataType) *LargeListType { + if t == nil { + panic("arrow: nil DataType") + } + return &LargeListType{ListType{elem: Field{Name: "item", Type: t, Nullable: true}}} +} + +// LargeListOfNonNullable is like ListOf but NullableElem defaults to false, indicating +// that the child type should be marked as non-nullable. +func LargeListOfNonNullable(t DataType) *LargeListType { + if t == nil { + panic("arrow: nil DataType") + } + return &LargeListType{ListType{elem: Field{Name: "item", Type: t, Nullable: false}}} +} + +// FixedSizeListType describes a nested type in which each array slot contains +// a fixed-size sequence of values, all having the same relative type. +type FixedSizeListType struct { + n int32 // number of elements in the list + elem Field +} + +func FixedSizeListOfField(n int32, f Field) *FixedSizeListType { + if f.Type == nil { + panic("arrow: nil DataType") + } + if n <= 0 { + panic("arrow: invalid size") + } + return &FixedSizeListType{n: n, elem: f} +} + +// FixedSizeListOf returns the list type with element type t. +// For example, if t represents int32, FixedSizeListOf(10, t) represents [10]int32. +// +// FixedSizeListOf panics if t is nil or invalid. +// FixedSizeListOf panics if n is <= 0. +// NullableElem defaults to true +func FixedSizeListOf(n int32, t DataType) *FixedSizeListType { + if t == nil { + panic("arrow: nil DataType") + } + if n <= 0 { + panic("arrow: invalid size") + } + return &FixedSizeListType{n: n, elem: Field{Name: "item", Type: t, Nullable: true}} +} + +// FixedSizeListOfNonNullable is like FixedSizeListOf but NullableElem defaults to false +// indicating that the child type should be marked as non-nullable. +func FixedSizeListOfNonNullable(n int32, t DataType) *FixedSizeListType { + if t == nil { + panic("arrow: nil DataType") + } + if n <= 0 { + panic("arrow: invalid size") + } + return &FixedSizeListType{n: n, elem: Field{Name: "item", Type: t, Nullable: false}} +} + +func (*FixedSizeListType) ID() Type { return FIXED_SIZE_LIST } +func (*FixedSizeListType) Name() string { return "fixed_size_list" } +func (t *FixedSizeListType) String() string { + if t.elem.Nullable { + return fmt.Sprintf("fixed_size_list<%s: %s, nullable>[%d]", t.elem.Name, t.elem.Type, t.n) + } + return fmt.Sprintf("fixed_size_list<%s: %s>[%d]", t.elem.Name, t.elem.Type, t.n) +} + +func (t *FixedSizeListType) SetElemNullable(n bool) { t.elem.Nullable = n } + +// Elem returns the FixedSizeListType's element type. +func (t *FixedSizeListType) Elem() DataType { return t.elem.Type } + +// Len returns the FixedSizeListType's size. +func (t *FixedSizeListType) Len() int32 { return t.n } + +func (t *FixedSizeListType) ElemField() Field { + return t.elem +} + +func (t *FixedSizeListType) Fingerprint() string { + child := t.elem.Type.Fingerprint() + if len(child) > 0 { + return fmt.Sprintf("%s[%d]{%s}", typeFingerprint(t), t.n, child) + } + return "" +} + +func (t *FixedSizeListType) Fields() []Field { return []Field{t.ElemField()} } + +func (*FixedSizeListType) Layout() DataTypeLayout { + return DataTypeLayout{Buffers: []BufferSpec{SpecBitmap()}} +} + +type ListViewType struct { + elem Field +} + +func ListViewOfField(f Field) *ListViewType { + if f.Type == nil { + panic("arrow: nil DataType") + } + return &ListViewType{elem: f} +} + +// ListViewOf returns the list-view type with element type t. +// For example, if t represents int32, ListViewOf(t) represents []int32. +// +// ListViewOf panics if t is nil or invalid. NullableElem defaults to true +func ListViewOf(t DataType) *ListViewType { + if t == nil { + panic("arrow: nil DataType") + } + return &ListViewType{elem: Field{Name: "item", Type: t, Nullable: true}} +} + +// ListViewOfNonNullable is like ListViewOf but NullableElem defaults to false, indicating +// that the child type should be marked as non-nullable. +func ListViewOfNonNullable(t DataType) *ListViewType { + if t == nil { + panic("arrow: nil DataType") + } + return &ListViewType{elem: Field{Name: "item", Type: t, Nullable: false}} +} + +func (*ListViewType) ID() Type { return LIST_VIEW } +func (*ListViewType) Name() string { return "list_view" } + +func (t *ListViewType) String() string { + if t.elem.Nullable { + return fmt.Sprintf("list_view<%s: %s, nullable>", t.elem.Name, t.elem.Type) + } + return fmt.Sprintf("list_view<%s: %s>", t.elem.Name, t.elem.Type) +} + +func (t *ListViewType) Fingerprint() string { + child := t.elem.Type.Fingerprint() + if len(child) > 0 { + return typeFingerprint(t) + "{" + child + "}" + } + return "" +} + +func (t *ListViewType) SetElemMetadata(md Metadata) { t.elem.Metadata = md } + +func (t *ListViewType) SetElemNullable(n bool) { t.elem.Nullable = n } + +// Elem returns the ListViewType's element type. +func (t *ListViewType) Elem() DataType { return t.elem.Type } + +func (t *ListViewType) ElemField() Field { + return t.elem +} + +func (t *ListViewType) Fields() []Field { return []Field{t.ElemField()} } + +func (*ListViewType) Layout() DataTypeLayout { + return DataTypeLayout{Buffers: []BufferSpec{SpecBitmap(), SpecFixedWidth(Int32SizeBytes), SpecFixedWidth(Int32SizeBytes)}} +} + +func (*ListViewType) OffsetTypeTraits() OffsetTraits { return Int32Traits } + +type LargeListViewType struct { + elem Field +} + +func LargeListViewOfField(f Field) *LargeListViewType { + if f.Type == nil { + panic("arrow: nil DataType") + } + return &LargeListViewType{elem: f} +} + +// LargeListViewOf returns the list-view type with element type t. +// For example, if t represents int32, LargeListViewOf(t) represents []int32. +// +// LargeListViewOf panics if t is nil or invalid. NullableElem defaults to true +func LargeListViewOf(t DataType) *LargeListViewType { + if t == nil { + panic("arrow: nil DataType") + } + return &LargeListViewType{elem: Field{Name: "item", Type: t, Nullable: true}} +} + +// LargeListViewOfNonNullable is like LargeListViewOf but NullableElem defaults +// to false, indicating that the child type should be marked as non-nullable. +func LargeListViewOfNonNullable(t DataType) *LargeListViewType { + if t == nil { + panic("arrow: nil DataType") + } + return &LargeListViewType{elem: Field{Name: "item", Type: t, Nullable: false}} +} + +func (*LargeListViewType) ID() Type { return LARGE_LIST_VIEW } +func (*LargeListViewType) Name() string { return "large_list_view" } + +func (t *LargeListViewType) String() string { + if t.elem.Nullable { + return fmt.Sprintf("large_list_view<%s: %s, nullable>", t.elem.Name, t.elem.Type) + } + return fmt.Sprintf("large_list_view<%s: %s>", t.elem.Name, t.elem.Type) +} + +func (t *LargeListViewType) Fingerprint() string { + child := t.elem.Type.Fingerprint() + if len(child) > 0 { + return typeFingerprint(t) + "{" + child + "}" + } + return "" +} + +func (t *LargeListViewType) SetElemMetadata(md Metadata) { t.elem.Metadata = md } + +func (t *LargeListViewType) SetElemNullable(n bool) { t.elem.Nullable = n } + +// Elem returns the LargeListViewType's element type. +func (t *LargeListViewType) Elem() DataType { return t.elem.Type } + +func (t *LargeListViewType) ElemField() Field { + return t.elem +} + +func (t *LargeListViewType) Fields() []Field { return []Field{t.ElemField()} } + +func (*LargeListViewType) Layout() DataTypeLayout { + return DataTypeLayout{Buffers: []BufferSpec{SpecBitmap(), SpecFixedWidth(Int64SizeBytes), SpecFixedWidth(Int64SizeBytes)}} +} + +func (*LargeListViewType) OffsetTypeTraits() OffsetTraits { return Int64Traits } + +// StructType describes a nested type parameterized by an ordered sequence +// of relative types, called its fields. +type StructType struct { + fields []Field + index map[string][]int + meta Metadata +} + +// StructOf returns the struct type with fields fs. +// +// StructOf panics if there is a field with an invalid DataType. +func StructOf(fs ...Field) *StructType { + n := len(fs) + if n == 0 { + return &StructType{} + } + + t := &StructType{ + fields: make([]Field, n), + index: make(map[string][]int, n), + } + for i, f := range fs { + if f.Type == nil { + panic("arrow: field with nil DataType") + } + t.fields[i] = Field{ + Name: f.Name, + Type: f.Type, + Nullable: f.Nullable, + Metadata: f.Metadata.clone(), + } + if indices, exists := t.index[f.Name]; exists { + t.index[f.Name] = append(indices, i) + } else { + t.index[f.Name] = []int{i} + } + } + + return t +} + +func (*StructType) ID() Type { return STRUCT } +func (*StructType) Name() string { return "struct" } + +func (t *StructType) String() string { + var o strings.Builder + o.WriteString("struct<") + for i, f := range t.fields { + if i > 0 { + o.WriteString(", ") + } + o.WriteString(fmt.Sprintf("%s: %v", f.Name, f.Type)) + } + o.WriteString(">") + return o.String() +} + +// Fields method provides a copy of StructType fields +// (so it can be safely mutated and will not result in updating the StructType). +func (t *StructType) Fields() []Field { + fields := make([]Field, len(t.fields)) + copy(fields, t.fields) + return fields +} + +func (t *StructType) Field(i int) Field { return t.fields[i] } + +// FieldByName gets the field with the given name. +// +// If there are multiple fields with the given name, FieldByName +// returns the first such field. +func (t *StructType) FieldByName(name string) (Field, bool) { + i, ok := t.index[name] + if !ok { + return Field{}, false + } + return t.fields[i[0]], true +} + +// FieldIdx gets the index of the field with the given name. +// +// If there are multiple fields with the given name, FieldIdx returns +// the index of the first first such field. +func (t *StructType) FieldIdx(name string) (int, bool) { + i, ok := t.index[name] + if ok { + return i[0], true + } + return -1, false +} + +// FieldsByName returns all fields with the given name. +func (t *StructType) FieldsByName(n string) ([]Field, bool) { + indices, ok := t.index[n] + if !ok { + return nil, ok + } + fields := make([]Field, 0, len(indices)) + for _, v := range indices { + fields = append(fields, t.fields[v]) + } + return fields, ok +} + +// FieldIndices returns indices of all fields with the given name, or nil. +func (t *StructType) FieldIndices(name string) []int { + return t.index[name] +} + +func (t *StructType) Fingerprint() string { + var b strings.Builder + b.WriteString(typeFingerprint(t)) + b.WriteByte('{') + for _, c := range t.fields { + child := c.Fingerprint() + if len(child) == 0 { + return "" + } + b.WriteString(child) + b.WriteByte(';') + } + b.WriteByte('}') + return b.String() +} + +func (*StructType) Layout() DataTypeLayout { + return DataTypeLayout{Buffers: []BufferSpec{SpecBitmap()}} +} + +type MapType struct { + value *ListType + KeysSorted bool +} + +func MapOf(key, item DataType) *MapType { + if key == nil || item == nil { + panic("arrow: nil key or item type for MapType") + } + + return &MapType{value: ListOf(StructOf(Field{Name: "key", Type: key}, Field{Name: "value", Type: item, Nullable: true}))} +} + +func MapOfWithMetadata(key DataType, keyMetadata Metadata, item DataType, itemMetadata Metadata) *MapType { + if key == nil || item == nil { + panic("arrow: nil key or item type for MapType") + } + + return &MapType{value: ListOf(StructOf(Field{ + Name: "key", + Type: key, + Metadata: keyMetadata, + }, Field{ + Name: "value", + Type: item, + Nullable: true, + Metadata: itemMetadata, + }))} +} + +func (*MapType) ID() Type { return MAP } +func (*MapType) Name() string { return "map" } + +func (t *MapType) String() string { + var o strings.Builder + o.WriteString(fmt.Sprintf("map<%s, %s", + t.value.Elem().(*StructType).Field(0).Type, + t.value.Elem().(*StructType).Field(1).Type)) + if t.KeysSorted { + o.WriteString(", keys_sorted") + } + if t.ItemField().Nullable { + o.WriteString(", items_nullable") + } else { + o.WriteString(", items_non_nullable") + } + o.WriteString(">") + return o.String() +} + +func (t *MapType) KeyField() Field { return t.value.Elem().(*StructType).Field(0) } +func (t *MapType) KeyType() DataType { return t.KeyField().Type } +func (t *MapType) ItemField() Field { return t.value.Elem().(*StructType).Field(1) } +func (t *MapType) ItemType() DataType { return t.ItemField().Type } + +// Deprecated: use MapType.Elem().(*StructType) instead +func (t *MapType) ValueType() *StructType { return t.Elem().(*StructType) } + +// Deprecated: use MapType.ElemField() instead +func (t *MapType) ValueField() Field { return t.ElemField() } + +// Elem returns the MapType's element type (if treating MapType as ListLikeType) +func (t *MapType) Elem() DataType { return t.value.Elem() } + +// ElemField returns the MapType's element field (if treating MapType as ListLikeType) +func (t *MapType) ElemField() Field { return Field{Name: "entries", Type: t.Elem()} } + +func (t *MapType) SetItemNullable(nullable bool) { + t.value.Elem().(*StructType).fields[1].Nullable = nullable +} + +func (t *MapType) Fingerprint() string { + keyFingerprint := t.KeyType().Fingerprint() + itemFingerprint := t.ItemType().Fingerprint() + if keyFingerprint == "" || itemFingerprint == "" { + return "" + } + + fingerprint := typeFingerprint(t) + if t.KeysSorted { + fingerprint += "s" + } + return fingerprint + "{" + keyFingerprint + itemFingerprint + "}" +} + +func (t *MapType) Fields() []Field { return []Field{t.ElemField()} } + +func (t *MapType) Layout() DataTypeLayout { + return t.value.Layout() +} + +func (*MapType) OffsetTypeTraits() OffsetTraits { return Int32Traits } + +type ( + // UnionTypeCode is an alias to int8 which is the type of the ids + // used for union arrays. + UnionTypeCode = int8 + UnionMode int8 +) + +const ( + MaxUnionTypeCode UnionTypeCode = 127 + InvalidUnionChildID int = -1 + + SparseMode UnionMode = iota // SPARSE + DenseMode // DENSE +) + +// UnionType is an interface to encompass both Dense and Sparse Union types. +// +// A UnionType is a nested type where each logical value is taken +// from a single child. A buffer of 8-bit type ids (typed as UnionTypeCode) +// indicates which child a given logical value is to be taken from. This is +// represented as the "child id" or "child index", which is the index into the +// list of child fields for a given child. +type UnionType interface { + NestedType + // Mode returns either SparseMode or DenseMode depending on the current + // concrete data type. + Mode() UnionMode + // ChildIDs returns a slice of ints to map UnionTypeCode values to + // the index in the Fields that represents the given Type. It is + // initialized with all values being InvalidUnionChildID (-1) + // before being populated based on the TypeCodes and fields of the type. + // The field for a given type can be retrieved by Fields()[ChildIDs()[typeCode]] + ChildIDs() []int + // TypeCodes returns the list of available type codes for this union type + // which will correspond to indexes into the ChildIDs slice to locate the + // appropriate child. A union Array contains a buffer of these type codes + // which indicate for a given index, which child has the value for that index. + TypeCodes() []UnionTypeCode + // MaxTypeCode returns the value of the largest TypeCode in the list of typecodes + // that are defined by this Union type + MaxTypeCode() UnionTypeCode +} + +// UnionOf returns an appropriate union type for the given Mode (Sparse or Dense), +// child fields, and type codes. len(fields) == len(typeCodes) must be true, or else +// this will panic. len(fields) can be 0. +func UnionOf(mode UnionMode, fields []Field, typeCodes []UnionTypeCode) UnionType { + switch mode { + case SparseMode: + return SparseUnionOf(fields, typeCodes) + case DenseMode: + return DenseUnionOf(fields, typeCodes) + default: + panic("arrow: invalid union mode") + } +} + +type unionType struct { + children []Field + typeCodes []UnionTypeCode + childIDs [int(MaxUnionTypeCode) + 1]int +} + +func (t *unionType) init(fields []Field, typeCodes []UnionTypeCode) { + // initialize all child IDs to -1 + t.childIDs[0] = InvalidUnionChildID + for i := 1; i < len(t.childIDs); i *= 2 { + copy(t.childIDs[i:], t.childIDs[:i]) + } + + t.children = fields + t.typeCodes = typeCodes + + for i, tc := range t.typeCodes { + t.childIDs[tc] = i + } +} + +// Fields method provides a copy of union type fields +// (so it can be safely mutated and will not result in updating the union type). +func (t *unionType) Fields() []Field { + fields := make([]Field, len(t.children)) + copy(fields, t.children) + return fields +} + +func (t *unionType) TypeCodes() []UnionTypeCode { return t.typeCodes } +func (t *unionType) ChildIDs() []int { return t.childIDs[:] } + +func (t *unionType) validate(fields []Field, typeCodes []UnionTypeCode, _ UnionMode) error { + if len(fields) != len(typeCodes) { + return errors.New("arrow: union types should have the same number of fields as type codes") + } + + for _, c := range typeCodes { + if c < 0 || c > MaxUnionTypeCode { + return errors.New("arrow: union type code out of bounds") + } + } + return nil +} + +func (t *unionType) MaxTypeCode() (max UnionTypeCode) { + if len(t.typeCodes) == 0 { + return + } + + max = t.typeCodes[0] + for _, c := range t.typeCodes[1:] { + if c > max { + max = c + } + } + return +} + +func (t *unionType) String() string { + var b strings.Builder + b.WriteByte('<') + for i := range t.typeCodes { + if i != 0 { + b.WriteString(", ") + } + fmt.Fprintf(&b, "%s=%d", t.children[i], t.typeCodes[i]) + } + b.WriteByte('>') + return b.String() +} + +func (t *unionType) fingerprint() string { + var b strings.Builder + for _, c := range t.typeCodes { + fmt.Fprintf(&b, ":%d", c) + } + b.WriteString("]{") + for _, c := range t.children { + fingerprint := c.Fingerprint() + if len(fingerprint) == 0 { + return "" + } + b.WriteString(fingerprint) + b.WriteByte(';') + } + b.WriteByte('}') + return b.String() +} + +func fieldsFromArrays(arrays []Array, names ...string) (ret []Field) { + ret = make([]Field, len(arrays)) + if len(names) == 0 { + for i, c := range arrays { + ret[i] = Field{Name: strconv.Itoa(i), Type: c.DataType(), Nullable: true} + } + } else { + debug.Assert(len(names) == len(arrays), "mismatch of arrays and names") + for i, c := range arrays { + ret[i] = Field{Name: names[i], Type: c.DataType(), Nullable: true} + } + } + return +} + +// SparseUnionType is the concrete type for Sparse union data. +// +// A sparse union is a nested type where each logical value is taken +// from a single child. A buffer of 8-bit type ids indicates which child +// a given logical value is to be taken from. +// +// In a sparse union, each child array will have the same length as the +// union array itself, regardless of the actual number of union values which +// refer to it. +// +// Unlike most other types, unions do not have a top-level validity bitmap. +type SparseUnionType struct { + unionType +} + +// SparseUnionFromArrays enables creating a union type from a list of Arrays, +// field names, and type codes. len(fields) should be either 0 or equal to len(children). +// len(codes) should also be either 0, or equal to len(children). +// +// If len(fields) == 0, then the fields will be named numerically as "0", "1", "2"... +// and so on. If len(codes) == 0, then the type codes will be constructed as +// [0, 1, 2, ..., n]. +func SparseUnionFromArrays(children []Array, fields []string, codes []UnionTypeCode) *SparseUnionType { + if len(codes) == 0 { + codes = make([]UnionTypeCode, len(children)) + for i := range children { + codes[i] = UnionTypeCode(i) + } + } + return SparseUnionOf(fieldsFromArrays(children, fields...), codes) +} + +// SparseUnionOf is equivalent to UnionOf(arrow.SparseMode, fields, typeCodes), +// constructing a SparseUnionType from a list of fields and type codes. +// +// If len(fields) != len(typeCodes) this will panic. They are allowed to be +// of length 0. +func SparseUnionOf(fields []Field, typeCodes []UnionTypeCode) *SparseUnionType { + ret := &SparseUnionType{} + if err := ret.validate(fields, typeCodes, ret.Mode()); err != nil { + panic(err) + } + ret.init(fields, typeCodes) + return ret +} + +func (SparseUnionType) ID() Type { return SPARSE_UNION } +func (SparseUnionType) Name() string { return "sparse_union" } +func (SparseUnionType) Mode() UnionMode { return SparseMode } +func (t *SparseUnionType) Fingerprint() string { + return typeFingerprint(t) + "[s" + t.fingerprint() +} +func (SparseUnionType) Layout() DataTypeLayout { + return DataTypeLayout{Buffers: []BufferSpec{SpecFixedWidth(Uint8SizeBytes)}} +} +func (t *SparseUnionType) String() string { + return t.Name() + t.unionType.String() +} + +// DenseUnionType is the concrete type for dense union data. +// +// A dense union is a nested type where each logical value is taken from a +// single child, at a specific offset. A buffer of 8-bit type ids (typed +// as UnionTypeCode) indicates which child a given logical value is to be +// taken from and a buffer of 32-bit offsets indicating which physical position +// in the given child array has the logical value for that index. +// +// Unlike a sparse union, a dense union allows encoding only the child values +// which are actually referred to by the union array. This is counterbalanced +// by the additional footprint of the offsets buffer, and the additional +// indirection cost when looking up values. +// +// Unlike most other types, unions don't have a top-level validity bitmap +type DenseUnionType struct { + unionType +} + +// DenseUnionFromArrays enables creating a union type from a list of Arrays, +// field names, and type codes. len(fields) should be either 0 or equal to len(children). +// len(codes) should also be either 0, or equal to len(children). +// +// If len(fields) == 0, then the fields will be named numerically as "0", "1", "2"... +// and so on. If len(codes) == 0, then the type codes will be constructed as +// [0, 1, 2, ..., n]. +func DenseUnionFromArrays(children []Array, fields []string, codes []UnionTypeCode) *DenseUnionType { + if len(codes) == 0 { + codes = make([]UnionTypeCode, len(children)) + for i := range children { + codes[i] = UnionTypeCode(i) + } + } + return DenseUnionOf(fieldsFromArrays(children, fields...), codes) +} + +// DenseUnionOf is equivalent to UnionOf(arrow.DenseMode, fields, typeCodes), +// constructing a SparseUnionType from a list of fields and type codes. +// +// If len(fields) != len(typeCodes) this will panic. They are allowed to be +// of length 0. +func DenseUnionOf(fields []Field, typeCodes []UnionTypeCode) *DenseUnionType { + ret := &DenseUnionType{} + if err := ret.validate(fields, typeCodes, ret.Mode()); err != nil { + panic(err) + } + ret.init(fields, typeCodes) + return ret +} + +func (DenseUnionType) ID() Type { return DENSE_UNION } +func (DenseUnionType) Name() string { return "dense_union" } +func (DenseUnionType) Mode() UnionMode { return DenseMode } +func (t *DenseUnionType) Fingerprint() string { + return typeFingerprint(t) + "[s" + t.fingerprint() +} + +func (DenseUnionType) Layout() DataTypeLayout { + return DataTypeLayout{Buffers: []BufferSpec{SpecFixedWidth(Uint8SizeBytes), SpecFixedWidth(Int32SizeBytes)}} +} + +func (DenseUnionType) OffsetTypeTraits() OffsetTraits { return Int32Traits } + +func (t *DenseUnionType) String() string { + return t.Name() + t.unionType.String() +} + +type Field struct { + Name string // Field name + Type DataType // The field's data type + Nullable bool // Fields can be nullable + Metadata Metadata // The field's metadata, if any +} + +func (f Field) Fingerprint() string { + typeFingerprint := f.Type.Fingerprint() + if typeFingerprint == "" { + return "" + } + + var b strings.Builder + b.WriteByte('F') + if f.Nullable { + b.WriteByte('n') + } else { + b.WriteByte('N') + } + b.WriteString(f.Name) + b.WriteByte('{') + b.WriteString(typeFingerprint) + b.WriteByte('}') + return b.String() +} + +func (f Field) HasMetadata() bool { return f.Metadata.Len() != 0 } + +func (f Field) Equal(o Field) bool { + switch { + case f.Name != o.Name: + return false + case f.Nullable != o.Nullable: + return false + case !TypeEqual(f.Type, o.Type, CheckMetadata()): + return false + case !f.Metadata.Equal(o.Metadata): + return false + } + return true +} + +func (f Field) String() string { + var o strings.Builder + nullable := "" + if f.Nullable { + nullable = ", nullable" + } + fmt.Fprintf(&o, "%s: type=%v%v", f.Name, f.Type, nullable) + if f.HasMetadata() { + fmt.Fprintf(&o, "\n%*.smetadata: %v", len(f.Name)+2, "", f.Metadata) + } + return o.String() +} + +var ( + _ DataType = (*ListType)(nil) + _ DataType = (*LargeListType)(nil) + _ DataType = (*FixedSizeListType)(nil) + _ DataType = (*StructType)(nil) + _ DataType = (*MapType)(nil) + _ DataType = (*DenseUnionType)(nil) + _ DataType = (*SparseUnionType)(nil) + + _ NestedType = (*ListType)(nil) + _ NestedType = (*LargeListType)(nil) + _ NestedType = (*FixedSizeListType)(nil) + _ NestedType = (*MapType)(nil) + _ NestedType = (*DenseUnionType)(nil) + _ NestedType = (*SparseUnionType)(nil) + + _ ListLikeType = (*ListType)(nil) + _ ListLikeType = (*LargeListType)(nil) + _ ListLikeType = (*FixedSizeListType)(nil) + _ ListLikeType = (*MapType)(nil) + + _ VarLenListLikeType = (*ListType)(nil) + _ VarLenListLikeType = (*LargeListType)(nil) + _ VarLenListLikeType = (*ListViewType)(nil) + _ VarLenListLikeType = (*LargeListViewType)(nil) + _ VarLenListLikeType = (*FixedSizeListType)(nil) + _ VarLenListLikeType = (*MapType)(nil) +) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/datatype_null.go b/vendor/github.com/apache/arrow/go/v14/arrow/datatype_null.go new file mode 100644 index 000000000..2d2454c65 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/datatype_null.go @@ -0,0 +1,33 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package arrow + +// NullType describes a degenerate array, with zero physical storage. +type NullType struct{} + +func (*NullType) ID() Type { return NULL } +func (*NullType) Name() string { return "null" } +func (*NullType) String() string { return "null" } +func (*NullType) Fingerprint() string { return typeIDFingerprint(NULL) } +func (*NullType) Layout() DataTypeLayout { + return DataTypeLayout{Buffers: []BufferSpec{SpecAlwaysNull()}} +} + +var ( + Null *NullType + _ DataType = Null +) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/datatype_numeric.gen.go b/vendor/github.com/apache/arrow/go/v14/arrow/datatype_numeric.gen.go new file mode 100644 index 000000000..62cbd9001 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/datatype_numeric.gen.go @@ -0,0 +1,206 @@ +// Code generated by datatype_numeric.gen.go.tmpl. DO NOT EDIT. + +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package arrow + +type Int8Type struct{} + +func (t *Int8Type) ID() Type { return INT8 } +func (t *Int8Type) Name() string { return "int8" } +func (t *Int8Type) String() string { return "int8" } +func (t *Int8Type) BitWidth() int { return 8 } +func (t *Int8Type) Bytes() int { return Int8SizeBytes } +func (t *Int8Type) Fingerprint() string { return typeFingerprint(t) } +func (t *Int8Type) Layout() DataTypeLayout { + return DataTypeLayout{Buffers: []BufferSpec{ + SpecBitmap(), SpecFixedWidth(Int8SizeBytes)}} +} + +type Int16Type struct{} + +func (t *Int16Type) ID() Type { return INT16 } +func (t *Int16Type) Name() string { return "int16" } +func (t *Int16Type) String() string { return "int16" } +func (t *Int16Type) BitWidth() int { return 16 } +func (t *Int16Type) Bytes() int { return Int16SizeBytes } +func (t *Int16Type) Fingerprint() string { return typeFingerprint(t) } +func (t *Int16Type) Layout() DataTypeLayout { + return DataTypeLayout{Buffers: []BufferSpec{ + SpecBitmap(), SpecFixedWidth(Int16SizeBytes)}} +} + +type Int32Type struct{} + +func (t *Int32Type) ID() Type { return INT32 } +func (t *Int32Type) Name() string { return "int32" } +func (t *Int32Type) String() string { return "int32" } +func (t *Int32Type) BitWidth() int { return 32 } +func (t *Int32Type) Bytes() int { return Int32SizeBytes } +func (t *Int32Type) Fingerprint() string { return typeFingerprint(t) } +func (t *Int32Type) Layout() DataTypeLayout { + return DataTypeLayout{Buffers: []BufferSpec{ + SpecBitmap(), SpecFixedWidth(Int32SizeBytes)}} +} + +type Int64Type struct{} + +func (t *Int64Type) ID() Type { return INT64 } +func (t *Int64Type) Name() string { return "int64" } +func (t *Int64Type) String() string { return "int64" } +func (t *Int64Type) BitWidth() int { return 64 } +func (t *Int64Type) Bytes() int { return Int64SizeBytes } +func (t *Int64Type) Fingerprint() string { return typeFingerprint(t) } +func (t *Int64Type) Layout() DataTypeLayout { + return DataTypeLayout{Buffers: []BufferSpec{ + SpecBitmap(), SpecFixedWidth(Int64SizeBytes)}} +} + +type Uint8Type struct{} + +func (t *Uint8Type) ID() Type { return UINT8 } +func (t *Uint8Type) Name() string { return "uint8" } +func (t *Uint8Type) String() string { return "uint8" } +func (t *Uint8Type) BitWidth() int { return 8 } +func (t *Uint8Type) Bytes() int { return Uint8SizeBytes } +func (t *Uint8Type) Fingerprint() string { return typeFingerprint(t) } +func (t *Uint8Type) Layout() DataTypeLayout { + return DataTypeLayout{Buffers: []BufferSpec{ + SpecBitmap(), SpecFixedWidth(Uint8SizeBytes)}} +} + +type Uint16Type struct{} + +func (t *Uint16Type) ID() Type { return UINT16 } +func (t *Uint16Type) Name() string { return "uint16" } +func (t *Uint16Type) String() string { return "uint16" } +func (t *Uint16Type) BitWidth() int { return 16 } +func (t *Uint16Type) Bytes() int { return Uint16SizeBytes } +func (t *Uint16Type) Fingerprint() string { return typeFingerprint(t) } +func (t *Uint16Type) Layout() DataTypeLayout { + return DataTypeLayout{Buffers: []BufferSpec{ + SpecBitmap(), SpecFixedWidth(Uint16SizeBytes)}} +} + +type Uint32Type struct{} + +func (t *Uint32Type) ID() Type { return UINT32 } +func (t *Uint32Type) Name() string { return "uint32" } +func (t *Uint32Type) String() string { return "uint32" } +func (t *Uint32Type) BitWidth() int { return 32 } +func (t *Uint32Type) Bytes() int { return Uint32SizeBytes } +func (t *Uint32Type) Fingerprint() string { return typeFingerprint(t) } +func (t *Uint32Type) Layout() DataTypeLayout { + return DataTypeLayout{Buffers: []BufferSpec{ + SpecBitmap(), SpecFixedWidth(Uint32SizeBytes)}} +} + +type Uint64Type struct{} + +func (t *Uint64Type) ID() Type { return UINT64 } +func (t *Uint64Type) Name() string { return "uint64" } +func (t *Uint64Type) String() string { return "uint64" } +func (t *Uint64Type) BitWidth() int { return 64 } +func (t *Uint64Type) Bytes() int { return Uint64SizeBytes } +func (t *Uint64Type) Fingerprint() string { return typeFingerprint(t) } +func (t *Uint64Type) Layout() DataTypeLayout { + return DataTypeLayout{Buffers: []BufferSpec{ + SpecBitmap(), SpecFixedWidth(Uint64SizeBytes)}} +} + +type Float32Type struct{} + +func (t *Float32Type) ID() Type { return FLOAT32 } +func (t *Float32Type) Name() string { return "float32" } +func (t *Float32Type) String() string { return "float32" } +func (t *Float32Type) BitWidth() int { return 32 } +func (t *Float32Type) Bytes() int { return Float32SizeBytes } +func (t *Float32Type) Fingerprint() string { return typeFingerprint(t) } +func (t *Float32Type) Layout() DataTypeLayout { + return DataTypeLayout{Buffers: []BufferSpec{ + SpecBitmap(), SpecFixedWidth(Float32SizeBytes)}} +} + +type Float64Type struct{} + +func (t *Float64Type) ID() Type { return FLOAT64 } +func (t *Float64Type) Name() string { return "float64" } +func (t *Float64Type) String() string { return "float64" } +func (t *Float64Type) BitWidth() int { return 64 } +func (t *Float64Type) Bytes() int { return Float64SizeBytes } +func (t *Float64Type) Fingerprint() string { return typeFingerprint(t) } +func (t *Float64Type) Layout() DataTypeLayout { + return DataTypeLayout{Buffers: []BufferSpec{ + SpecBitmap(), SpecFixedWidth(Float64SizeBytes)}} +} + +type Date32Type struct{} + +func (t *Date32Type) ID() Type { return DATE32 } +func (t *Date32Type) Name() string { return "date32" } +func (t *Date32Type) String() string { return "date32" } +func (t *Date32Type) BitWidth() int { return 32 } +func (t *Date32Type) Bytes() int { return Date32SizeBytes } +func (t *Date32Type) Fingerprint() string { return typeFingerprint(t) } +func (t *Date32Type) Layout() DataTypeLayout { + return DataTypeLayout{Buffers: []BufferSpec{ + SpecBitmap(), SpecFixedWidth(Date32SizeBytes)}} +} + +type Date64Type struct{} + +func (t *Date64Type) ID() Type { return DATE64 } +func (t *Date64Type) Name() string { return "date64" } +func (t *Date64Type) String() string { return "date64" } +func (t *Date64Type) BitWidth() int { return 64 } +func (t *Date64Type) Bytes() int { return Date64SizeBytes } +func (t *Date64Type) Fingerprint() string { return typeFingerprint(t) } +func (t *Date64Type) Layout() DataTypeLayout { + return DataTypeLayout{Buffers: []BufferSpec{ + SpecBitmap(), SpecFixedWidth(Date64SizeBytes)}} +} + +var ( + PrimitiveTypes = struct { + Int8 DataType + Int16 DataType + Int32 DataType + Int64 DataType + Uint8 DataType + Uint16 DataType + Uint32 DataType + Uint64 DataType + Float32 DataType + Float64 DataType + Date32 DataType + Date64 DataType + }{ + + Int8: &Int8Type{}, + Int16: &Int16Type{}, + Int32: &Int32Type{}, + Int64: &Int64Type{}, + Uint8: &Uint8Type{}, + Uint16: &Uint16Type{}, + Uint32: &Uint32Type{}, + Uint64: &Uint64Type{}, + Float32: &Float32Type{}, + Float64: &Float64Type{}, + Date32: &Date32Type{}, + Date64: &Date64Type{}, + } +) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/datatype_numeric.gen.go.tmpl b/vendor/github.com/apache/arrow/go/v14/arrow/datatype_numeric.gen.go.tmpl new file mode 100644 index 000000000..611046afc --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/datatype_numeric.gen.go.tmpl @@ -0,0 +1,45 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package arrow + +{{range .In}} +type {{.Name}}Type struct {} + +func (t *{{.Name}}Type) ID() Type { return {{.Name|upper}} } +func (t *{{.Name}}Type) Name() string { return "{{.Name|lower}}" } +func (t *{{.Name}}Type) String() string { return "{{.Name|lower}}" } +func (t *{{.Name}}Type) BitWidth() int { return {{.Size}} } +func (t *{{.Name}}Type) Bytes() int { return {{.Name}}SizeBytes } +func (t *{{.Name}}Type) Fingerprint() string { return typeFingerprint(t) } +func (t *{{.Name}}Type) Layout() DataTypeLayout { + return DataTypeLayout{Buffers: []BufferSpec{ + SpecBitmap(), SpecFixedWidth({{.Name}}SizeBytes)}} +} + +{{end}} + +var ( + PrimitiveTypes = struct { +{{range .In}} + {{.Name}} DataType +{{- end}} + }{ +{{range .In}} + {{.Name}}: &{{.Name}}Type{}, +{{- end}} + } +) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/datatype_numeric.gen.go.tmpldata b/vendor/github.com/apache/arrow/go/v14/arrow/datatype_numeric.gen.go.tmpldata new file mode 100644 index 000000000..12e69fe60 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/datatype_numeric.gen.go.tmpldata @@ -0,0 +1,66 @@ +[ + { + "Name": "Int8", + "Type": "int8", + "Size": 8 + }, + { + "Name": "Int16", + "Type": "int16", + "Size": 16 + }, + { + "Name": "Int32", + "Type": "int32", + "Size": 32 + }, + { + "Name": "Int64", + "Type": "int64", + "Size": 64 + }, + { + "Name": "Uint8", + "Type": "uint8", + "Size": 8 + }, + { + "Name": "Uint16", + "Type": "uint16", + "Size": 16 + }, + { + "Name": "Uint32", + "Type": "uint32", + "Size": 32 + }, + { + "Name": "Uint64", + "Type": "uint64", + "Size": 64 + }, + { + "Name": "Float32", + "Type": "float32", + "Size": 32 + }, + { + "Name": "Float64", + "Type": "float64", + "Size": 64 + }, + { + "Name": "Date32", + "Type": "date32", + "QualifiedType": "arrow.Date32", + "InternalType": "int32", + "Size": 32 + }, + { + "Name": "Date64", + "Type": "date64", + "QualifiedType": "arrow.Date64", + "InternalType": "int64", + "Size": 64 + } +] diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/decimal128/decimal128.go b/vendor/github.com/apache/arrow/go/v14/arrow/decimal128/decimal128.go new file mode 100644 index 000000000..898d7b427 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/decimal128/decimal128.go @@ -0,0 +1,611 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package decimal128 + +import ( + "errors" + "fmt" + "math" + "math/big" + "math/bits" + + "github.com/apache/arrow/go/v14/arrow/internal/debug" +) + +const ( + MaxPrecision = 38 + MaxScale = 38 +) + +var ( + MaxDecimal128 = New(542101086242752217, 687399551400673280-1) +) + +func GetMaxValue(prec int32) Num { + return scaleMultipliers[prec].Sub(FromU64(1)) +} + +// Num represents a signed 128-bit integer in two's complement. +// Calculations wrap around and overflow is ignored. +// +// For a discussion of the algorithms, look at Knuth's volume 2, +// Semi-numerical Algorithms section 4.3.1. +// +// Adapted from the Apache ORC C++ implementation +type Num struct { + lo uint64 // low bits + hi int64 // high bits +} + +// New returns a new signed 128-bit integer value. +func New(hi int64, lo uint64) Num { + return Num{lo: lo, hi: hi} +} + +// FromU64 returns a new signed 128-bit integer value from the provided uint64 one. +func FromU64(v uint64) Num { + return New(0, v) +} + +// FromI64 returns a new signed 128-bit integer value from the provided int64 one. +func FromI64(v int64) Num { + switch { + case v > 0: + return New(0, uint64(v)) + case v < 0: + return New(-1, uint64(v)) + default: + return Num{} + } +} + +// FromBigInt will convert a big.Int to a Num, if the value in v has a +// BitLen > 128, this will panic. +func FromBigInt(v *big.Int) (n Num) { + bitlen := v.BitLen() + if bitlen > 127 { + panic("arrow/decimal128: cannot represent value larger than 128bits") + } else if bitlen == 0 { + // if bitlen is 0, then the value is 0 so return the default zeroed + // out n + return + } + + // if the value is negative, then get the high and low bytes from + // v, and then negate it. this is because Num uses a two's compliment + // representation of values and big.Int stores the value as a bool for + // the sign and the absolute value of the integer. This means that the + // raw bytes are *always* the absolute value. + b := v.Bits() + n.lo = uint64(b[0]) + if len(b) > 1 { + n.hi = int64(b[1]) + } + if v.Sign() < 0 { + return n.Negate() + } + return +} + +// Negate returns a copy of this Decimal128 value but with the sign negated +func (n Num) Negate() Num { + n.lo = ^n.lo + 1 + n.hi = ^n.hi + if n.lo == 0 { + n.hi += 1 + } + return n +} + +func (n Num) Add(rhs Num) Num { + n.hi += rhs.hi + var carry uint64 + n.lo, carry = bits.Add64(n.lo, rhs.lo, 0) + n.hi += int64(carry) + return n +} + +func (n Num) Sub(rhs Num) Num { + n.hi -= rhs.hi + var borrow uint64 + n.lo, borrow = bits.Sub64(n.lo, rhs.lo, 0) + n.hi -= int64(borrow) + return n +} + +func (n Num) Mul(rhs Num) Num { + hi, lo := bits.Mul64(n.lo, rhs.lo) + hi += (uint64(n.hi) * rhs.lo) + (n.lo * uint64(rhs.hi)) + return Num{hi: int64(hi), lo: lo} +} + +func (n Num) Div(rhs Num) (res, rem Num) { + b := n.BigInt() + out, remainder := b.QuoRem(b, rhs.BigInt(), &big.Int{}) + return FromBigInt(out), FromBigInt(remainder) +} + +func (n Num) Pow(rhs Num) Num { + b := n.BigInt() + return FromBigInt(b.Exp(b, rhs.BigInt(), nil)) +} + +func scalePositiveFloat64(v float64, prec, scale int32) (float64, error) { + var pscale float64 + if scale >= -38 && scale <= 38 { + pscale = float64PowersOfTen[scale+38] + } else { + pscale = math.Pow10(int(scale)) + } + + v *= pscale + v = math.RoundToEven(v) + maxabs := float64PowersOfTen[prec+38] + if v <= -maxabs || v >= maxabs { + return 0, fmt.Errorf("cannot convert %f to decimal128(precision=%d, scale=%d): overflow", v, prec, scale) + } + return v, nil +} + +func fromPositiveFloat64(v float64, prec, scale int32) (Num, error) { + v, err := scalePositiveFloat64(v, prec, scale) + if err != nil { + return Num{}, err + } + + hi := math.Floor(math.Ldexp(v, -64)) + low := v - math.Ldexp(hi, 64) + return Num{hi: int64(hi), lo: uint64(low)}, nil +} + +// this has to exist despite sharing some code with fromPositiveFloat64 +// because if we don't do the casts back to float32 in between each +// step, we end up with a significantly different answer! +// Aren't floating point values so much fun? +// +// example value to use: +// +// v := float32(1.8446746e+15) +// +// You'll end up with a different values if you do: +// +// FromFloat64(float64(v), 20, 4) +// +// vs +// +// FromFloat32(v, 20, 4) +// +// because float64(v) == 1844674629206016 rather than 1844674600000000 +func fromPositiveFloat32(v float32, prec, scale int32) (Num, error) { + val, err := scalePositiveFloat64(float64(v), prec, scale) + if err != nil { + return Num{}, err + } + + hi := float32(math.Floor(math.Ldexp(float64(float32(val)), -64))) + low := float32(val) - float32(math.Ldexp(float64(hi), 64)) + return Num{hi: int64(hi), lo: uint64(low)}, nil +} + +// FromFloat32 returns a new decimal128.Num constructed from the given float32 +// value using the provided precision and scale. Will return an error if the +// value cannot be accurately represented with the desired precision and scale. +func FromFloat32(v float32, prec, scale int32) (Num, error) { + if v < 0 { + dec, err := fromPositiveFloat32(-v, prec, scale) + if err != nil { + return dec, err + } + return dec.Negate(), nil + } + return fromPositiveFloat32(v, prec, scale) +} + +// FromFloat64 returns a new decimal128.Num constructed from the given float64 +// value using the provided precision and scale. Will return an error if the +// value cannot be accurately represented with the desired precision and scale. +func FromFloat64(v float64, prec, scale int32) (Num, error) { + if v < 0 { + dec, err := fromPositiveFloat64(-v, prec, scale) + if err != nil { + return dec, err + } + return dec.Negate(), nil + } + return fromPositiveFloat64(v, prec, scale) +} + +var pt5 = big.NewFloat(0.5) + +func FromString(v string, prec, scale int32) (n Num, err error) { + // time for some math! + // Our input precision means "number of digits of precision" but the + // math/big library refers to precision in floating point terms + // where it refers to the "number of bits of precision in the mantissa". + // So we need to figure out how many bits we should use for precision, + // based on the input precision. Too much precision and we're not rounding + // when we should. Too little precision and we round when we shouldn't. + // + // In general, the number of decimal digits you get from a given number + // of bits will be: + // + // digits = log[base 10](2^nbits) + // + // it thus follows that: + // + // digits = nbits * log[base 10](2) + // nbits = digits / log[base 10](2) + // + // So we need to account for our scale since we're going to be multiplying + // by 10^scale in order to get the integral value we're actually going to use + // So to get our number of bits we do: + // + // (prec + scale + 1) / log[base10](2) + // + // Finally, we still have a sign bit, so we -1 to account for the sign bit. + // Aren't floating point numbers fun? + var precInBits = uint(math.Round(float64(prec+scale+1)/math.Log10(2))) + 1 + + var out *big.Float + out, _, err = big.ParseFloat(v, 10, 127, big.ToNearestEven) + if err != nil { + return + } + + // Since we're going to truncate this to get an integer, we need to round + // the value instead because of edge cases so that we match how other implementations + // (e.g. C++) handles Decimal values. So if we're negative we'll subtract 0.5 and if + // we're positive we'll add 0.5. + out.Mul(out, big.NewFloat(math.Pow10(int(scale)))).SetPrec(precInBits) + if out.Signbit() { + out.Sub(out, pt5) + } else { + out.Add(out, pt5) + } + + var tmp big.Int + val, _ := out.Int(&tmp) + if val.BitLen() > 127 { + return Num{}, errors.New("bitlen too large for decimal128") + } + n = FromBigInt(val) + if !n.FitsInPrecision(prec) { + err = fmt.Errorf("val %v doesn't fit in precision %d", n, prec) + } + return +} + +// ToFloat32 returns a float32 value representative of this decimal128.Num, +// but with the given scale. +func (n Num) ToFloat32(scale int32) float32 { + return float32(n.ToFloat64(scale)) +} + +func (n Num) tofloat64Positive(scale int32) float64 { + const twoTo64 float64 = 1.8446744073709552e+19 + x := float64(n.hi) * twoTo64 + x += float64(n.lo) + if scale >= -38 && scale <= 38 { + return x * float64PowersOfTen[-scale+38] + } + + return x * math.Pow10(-int(scale)) +} + +// ToFloat64 returns a float64 value representative of this decimal128.Num, +// but with the given scale. +func (n Num) ToFloat64(scale int32) float64 { + if n.hi < 0 { + return -n.Negate().tofloat64Positive(scale) + } + return n.tofloat64Positive(scale) +} + +// LowBits returns the low bits of the two's complement representation of the number. +func (n Num) LowBits() uint64 { return n.lo } + +// HighBits returns the high bits of the two's complement representation of the number. +func (n Num) HighBits() int64 { return n.hi } + +// Sign returns: +// +// -1 if x < 0 +// +// 0 if x == 0 +// +// +1 if x > 0 +func (n Num) Sign() int { + if n == (Num{}) { + return 0 + } + return int(1 | (n.hi >> 63)) +} + +func toBigIntPositive(n Num) *big.Int { + return (&big.Int{}).SetBits([]big.Word{big.Word(n.lo), big.Word(n.hi)}) +} + +// while the code would be simpler to just do lsh/rsh and add +// it turns out from benchmarking that calling SetBits passing +// in the words and negating ends up being >2x faster +func (n Num) BigInt() *big.Int { + if n.Sign() < 0 { + b := toBigIntPositive(n.Negate()) + return b.Neg(b) + } + return toBigIntPositive(n) +} + +// Greater returns true if the value represented by n is > other +func (n Num) Greater(other Num) bool { + return other.Less(n) +} + +// GreaterEqual returns true if the value represented by n is >= other +func (n Num) GreaterEqual(other Num) bool { + return !n.Less(other) +} + +// Less returns true if the value represented by n is < other +func (n Num) Less(other Num) bool { + return n.hi < other.hi || (n.hi == other.hi && n.lo < other.lo) +} + +// LessEqual returns true if the value represented by n is <= other +func (n Num) LessEqual(other Num) bool { + return !n.Greater(other) +} + +// Max returns the largest Decimal128 that was passed in the arguments +func Max(first Num, rest ...Num) Num { + answer := first + for _, number := range rest { + if number.Greater(answer) { + answer = number + } + } + return answer +} + +// Min returns the smallest Decimal128 that was passed in the arguments +func Min(first Num, rest ...Num) Num { + answer := first + for _, number := range rest { + if number.Less(answer) { + answer = number + } + } + return answer +} + +// Cmp compares the numbers represented by n and other and returns: +// +// +1 if n > other +// 0 if n == other +// -1 if n < other +func (n Num) Cmp(other Num) int { + switch { + case n.Greater(other): + return 1 + case n.Less(other): + return -1 + } + return 0 +} + +// IncreaseScaleBy returns a new decimal128.Num with the value scaled up by +// the desired amount. Must be 0 <= increase <= 38. Any data loss from scaling +// is ignored. If you wish to prevent data loss, use Rescale which will +// return an error if data loss is detected. +func (n Num) IncreaseScaleBy(increase int32) Num { + debug.Assert(increase >= 0, "invalid increase scale for decimal128") + debug.Assert(increase <= 38, "invalid increase scale for decimal128") + + v := scaleMultipliers[increase].BigInt() + return FromBigInt(v.Mul(n.BigInt(), v)) +} + +// ReduceScaleBy returns a new decimal128.Num with the value scaled down by +// the desired amount and, if 'round' is true, the value will be rounded +// accordingly. Assumes 0 <= reduce <= 38. Any data loss from scaling +// is ignored. If you wish to prevent data loss, use Rescale which will +// return an error if data loss is detected. +func (n Num) ReduceScaleBy(reduce int32, round bool) Num { + debug.Assert(reduce >= 0, "invalid reduce scale for decimal128") + debug.Assert(reduce <= 38, "invalid reduce scale for decimal128") + + if reduce == 0 { + return n + } + + divisor := scaleMultipliers[reduce].BigInt() + result, remainder := divisor.QuoRem(n.BigInt(), divisor, (&big.Int{})) + if round { + divisorHalf := scaleMultipliersHalf[reduce] + if remainder.Abs(remainder).Cmp(divisorHalf.BigInt()) != -1 { + result.Add(result, big.NewInt(int64(n.Sign()))) + } + } + return FromBigInt(result) +} + +func (n Num) rescaleWouldCauseDataLoss(deltaScale int32, multiplier Num) (out Num, loss bool) { + var ( + value, result, remainder *big.Int + ) + value = n.BigInt() + if deltaScale < 0 { + debug.Assert(multiplier.lo != 0 || multiplier.hi != 0, "multiplier needs to not be zero") + result, remainder = (&big.Int{}).QuoRem(value, multiplier.BigInt(), (&big.Int{})) + return FromBigInt(result), remainder.Cmp(big.NewInt(0)) != 0 + } + + result = (&big.Int{}).Mul(value, multiplier.BigInt()) + out = FromBigInt(result) + cmp := result.Cmp(value) + if n.Sign() < 0 { + loss = cmp == 1 + } else { + loss = cmp == -1 + } + return +} + +// Rescale returns a new decimal128.Num with the value updated assuming +// the current value is scaled to originalScale with the new value scaled +// to newScale. If rescaling this way would cause data loss, an error is +// returned instead. +func (n Num) Rescale(originalScale, newScale int32) (out Num, err error) { + if originalScale == newScale { + return n, nil + } + + deltaScale := newScale - originalScale + absDeltaScale := int32(math.Abs(float64(deltaScale))) + + multiplier := scaleMultipliers[absDeltaScale] + var wouldHaveLoss bool + out, wouldHaveLoss = n.rescaleWouldCauseDataLoss(deltaScale, multiplier) + if wouldHaveLoss { + err = errors.New("rescale data loss") + } + return +} + +// Abs returns a new decimal128.Num that contains the absolute value of n +func (n Num) Abs() Num { + switch n.Sign() { + case -1: + return n.Negate() + } + return n +} + +// FitsInPrecision returns true or false if the value currently held by +// n would fit within precision (0 < prec <= 38) without losing any data. +func (n Num) FitsInPrecision(prec int32) bool { + debug.Assert(prec > 0, "precision must be > 0") + debug.Assert(prec <= 38, "precision must be <= 38") + return n.Abs().Less(scaleMultipliers[prec]) +} + +func (n Num) ToString(scale int32) string { + f := (&big.Float{}).SetInt(n.BigInt()) + f.Quo(f, (&big.Float{}).SetInt(scaleMultipliers[scale].BigInt())) + return f.Text('f', int(scale)) +} + +func GetScaleMultiplier(pow int) Num { return scaleMultipliers[pow] } + +func GetHalfScaleMultiplier(pow int) Num { return scaleMultipliersHalf[pow] } + +var ( + scaleMultipliers = [...]Num{ + FromU64(1), + FromU64(10), + FromU64(100), + FromU64(1000), + FromU64(10000), + FromU64(100000), + FromU64(1000000), + FromU64(10000000), + FromU64(100000000), + FromU64(1000000000), + FromU64(10000000000), + FromU64(100000000000), + FromU64(1000000000000), + FromU64(10000000000000), + FromU64(100000000000000), + FromU64(1000000000000000), + FromU64(10000000000000000), + FromU64(100000000000000000), + FromU64(1000000000000000000), + New(0, 10000000000000000000), + New(5, 7766279631452241920), + New(54, 3875820019684212736), + New(542, 1864712049423024128), + New(5421, 200376420520689664), + New(54210, 2003764205206896640), + New(542101, 1590897978359414784), + New(5421010, 15908979783594147840), + New(54210108, 11515845246265065472), + New(542101086, 4477988020393345024), + New(5421010862, 7886392056514347008), + New(54210108624, 5076944270305263616), + New(542101086242, 13875954555633532928), + New(5421010862427, 9632337040368467968), + New(54210108624275, 4089650035136921600), + New(542101086242752, 4003012203950112768), + New(5421010862427522, 3136633892082024448), + New(54210108624275221, 12919594847110692864), + New(542101086242752217, 68739955140067328), + New(5421010862427522170, 687399551400673280), + } + + scaleMultipliersHalf = [...]Num{ + FromU64(0), + FromU64(5), + FromU64(50), + FromU64(500), + FromU64(5000), + FromU64(50000), + FromU64(500000), + FromU64(5000000), + FromU64(50000000), + FromU64(500000000), + FromU64(5000000000), + FromU64(50000000000), + FromU64(500000000000), + FromU64(5000000000000), + FromU64(50000000000000), + FromU64(500000000000000), + FromU64(5000000000000000), + FromU64(50000000000000000), + FromU64(500000000000000000), + FromU64(5000000000000000000), + New(2, 13106511852580896768), + New(27, 1937910009842106368), + New(271, 932356024711512064), + New(2710, 9323560247115120640), + New(27105, 1001882102603448320), + New(271050, 10018821026034483200), + New(2710505, 7954489891797073920), + New(27105054, 5757922623132532736), + New(271050543, 2238994010196672512), + New(2710505431, 3943196028257173504), + New(27105054312, 2538472135152631808), + New(271050543121, 6937977277816766464), + New(2710505431213, 14039540557039009792), + New(27105054312137, 11268197054423236608), + New(271050543121376, 2001506101975056384), + New(2710505431213761, 1568316946041012224), + New(27105054312137610, 15683169460410122240), + New(271050543121376108, 9257742014424809472), + New(2710505431213761085, 343699775700336640), + } + + float64PowersOfTen = [...]float64{ + 1e-38, 1e-37, 1e-36, 1e-35, 1e-34, 1e-33, 1e-32, 1e-31, 1e-30, 1e-29, + 1e-28, 1e-27, 1e-26, 1e-25, 1e-24, 1e-23, 1e-22, 1e-21, 1e-20, 1e-19, + 1e-18, 1e-17, 1e-16, 1e-15, 1e-14, 1e-13, 1e-12, 1e-11, 1e-10, 1e-9, + 1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1, 1e0, 1e1, + 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, + 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, + 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29, 1e30, 1e31, + 1e32, 1e33, 1e34, 1e35, 1e36, 1e37, 1e38, + } +) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/decimal256/decimal256.go b/vendor/github.com/apache/arrow/go/v14/arrow/decimal256/decimal256.go new file mode 100644 index 000000000..4bfcd4e04 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/decimal256/decimal256.go @@ -0,0 +1,693 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package decimal256 + +import ( + "errors" + "fmt" + "math" + "math/big" + "math/bits" + + "github.com/apache/arrow/go/v14/arrow/decimal128" + "github.com/apache/arrow/go/v14/arrow/internal/debug" +) + +const ( + MaxPrecision = 76 + MaxScale = 76 +) + +func GetMaxValue(prec int32) Num { + return scaleMultipliers[prec].Sub(FromU64(1)) +} + +type Num struct { + // arr[0] is the lowest bits, arr[3] is the highest bits + arr [4]uint64 +} + +// New returns a new signed 256-bit integer value where x1 contains +// the highest bits with the rest of the values in order down to the +// lowest bits +// +// ie: New(1, 2, 3, 4) returns with the elements in little-endian order +// {4, 3, 2, 1} but each value is still represented as the native endianness +func New(x1, x2, x3, x4 uint64) Num { + return Num{[4]uint64{x4, x3, x2, x1}} +} + +func (n Num) Array() [4]uint64 { return n.arr } + +func (n Num) LowBits() uint64 { return n.arr[0] } + +func FromDecimal128(n decimal128.Num) Num { + var topBits uint64 + if n.Sign() < 0 { + topBits = math.MaxUint64 + } + return New(topBits, topBits, uint64(n.HighBits()), n.LowBits()) +} + +func FromU64(v uint64) Num { + return Num{[4]uint64{v, 0, 0, 0}} +} + +func FromI64(v int64) Num { + switch { + case v > 0: + return New(0, 0, 0, uint64(v)) + case v < 0: + return New(math.MaxUint64, math.MaxUint64, math.MaxUint64, uint64(v)) + default: + return Num{} + } +} + +func (n Num) Negate() Num { + var carry uint64 = 1 + for i := range n.arr { + n.arr[i] = ^n.arr[i] + carry + if n.arr[i] != 0 { + carry = 0 + } + } + return n +} + +func (n Num) Add(rhs Num) Num { + var carry uint64 + for i, v := range n.arr { + n.arr[i], carry = bits.Add64(v, rhs.arr[i], carry) + } + return n +} + +func (n Num) Sub(rhs Num) Num { + return n.Add(rhs.Negate()) +} + +func (n Num) Mul(rhs Num) Num { + b := n.BigInt() + return FromBigInt(b.Mul(b, rhs.BigInt())) +} + +func (n Num) Div(rhs Num) (res, rem Num) { + b := n.BigInt() + out, remainder := b.QuoRem(b, rhs.BigInt(), &big.Int{}) + return FromBigInt(out), FromBigInt(remainder) +} + +func (n Num) Pow(rhs Num) Num { + b := n.BigInt() + return FromBigInt(b.Exp(b, rhs.BigInt(), nil)) +} + +var pt5 = big.NewFloat(0.5) + +func FromString(v string, prec, scale int32) (n Num, err error) { + // time for some math! + // Our input precision means "number of digits of precision" but the + // math/big library refers to precision in floating point terms + // where it refers to the "number of bits of precision in the mantissa". + // So we need to figure out how many bits we should use for precision, + // based on the input precision. Too much precision and we're not rounding + // when we should. Too little precision and we round when we shouldn't. + // + // In general, the number of decimal digits you get from a given number + // of bits will be: + // + // digits = log[base 10](2^nbits) + // + // it thus follows that: + // + // digits = nbits * log[base 10](2) + // nbits = digits / log[base 10](2) + // + // So we need to account for our scale since we're going to be multiplying + // by 10^scale in order to get the integral value we're actually going to use + // So to get our number of bits we do: + // + // (prec + scale + 1) / log[base10](2) + // + // Finally, we still have a sign bit, so we -1 to account for the sign bit. + // Aren't floating point numbers fun? + var precInBits = uint(math.Round(float64(prec+scale+1)/math.Log10(2))) + 1 + + var out *big.Float + out, _, err = big.ParseFloat(v, 10, 255, big.ToNearestEven) + if err != nil { + return + } + + out.Mul(out, big.NewFloat(math.Pow10(int(scale)))).SetPrec(precInBits) + // Since we're going to truncate this to get an integer, we need to round + // the value instead because of edge cases so that we match how other implementations + // (e.g. C++) handles Decimal values. So if we're negative we'll subtract 0.5 and if + // we're positive we'll add 0.5. + if out.Signbit() { + out.Sub(out, pt5) + } else { + out.Add(out, pt5) + } + + var tmp big.Int + val, _ := out.Int(&tmp) + if val.BitLen() > 255 { + return Num{}, errors.New("bitlen too large for decimal256") + } + n = FromBigInt(val) + if !n.FitsInPrecision(prec) { + err = fmt.Errorf("value %v doesn't fit in precision %d", n, prec) + } + return +} + +func FromFloat32(v float32, prec, scale int32) (Num, error) { + debug.Assert(prec > 0 && prec <= 76, "invalid precision for converting to decimal256") + + if math.IsInf(float64(v), 0) { + return Num{}, fmt.Errorf("cannot convert %f to decimal256", v) + } + + if v < 0 { + dec, err := fromPositiveFloat32(-v, prec, scale) + if err != nil { + return dec, err + } + return dec.Negate(), nil + } + return fromPositiveFloat32(v, prec, scale) +} + +func FromFloat64(v float64, prec, scale int32) (Num, error) { + debug.Assert(prec > 0 && prec <= 76, "invalid precision for converting to decimal256") + + if math.IsInf(v, 0) { + return Num{}, fmt.Errorf("cannot convert %f to decimal256", v) + } + + if v < 0 { + dec, err := fromPositiveFloat64(-v, prec, scale) + if err != nil { + return dec, err + } + return dec.Negate(), nil + } + return fromPositiveFloat64(v, prec, scale) +} + +// this has to exist despite sharing some code with fromPositiveFloat64 +// because if we don't do the casts back to float32 in between each +// step, we end up with a significantly different answer! +// Aren't floating point values so much fun? +// +// example value to use: +// +// v := float32(1.8446746e+15) +// +// You'll end up with a different values if you do: +// +// FromFloat64(float64(v), 20, 4) +// +// vs +// +// FromFloat32(v, 20, 4) +// +// because float64(v) == 1844674629206016 rather than 1844674600000000 +func fromPositiveFloat32(v float32, prec, scale int32) (Num, error) { + val, err := scalePositiveFloat64(float64(v), prec, scale) + if err != nil { + return Num{}, err + } + + v = float32(val) + var arr [4]float32 + arr[3] = float32(math.Floor(math.Ldexp(float64(v), -192))) + v -= float32(math.Ldexp(float64(arr[3]), 192)) + arr[2] = float32(math.Floor(math.Ldexp(float64(v), -128))) + v -= float32(math.Ldexp(float64(arr[2]), 128)) + arr[1] = float32(math.Floor(math.Ldexp(float64(v), -64))) + v -= float32(math.Ldexp(float64(arr[1]), 64)) + arr[0] = v + + debug.Assert(arr[3] >= 0, "bad conversion float64 to decimal256") + debug.Assert(arr[3] < 1.8446744073709552e+19, "bad conversion float64 to decimal256") // 2**64 + debug.Assert(arr[2] >= 0, "bad conversion float64 to decimal256") + debug.Assert(arr[2] < 1.8446744073709552e+19, "bad conversion float64 to decimal256") // 2**64 + debug.Assert(arr[1] >= 0, "bad conversion float64 to decimal256") + debug.Assert(arr[1] < 1.8446744073709552e+19, "bad conversion float64 to decimal256") // 2**64 + debug.Assert(arr[0] >= 0, "bad conversion float64 to decimal256") + debug.Assert(arr[0] < 1.8446744073709552e+19, "bad conversion float64 to decimal256") // 2**64 + return Num{[4]uint64{uint64(arr[0]), uint64(arr[1]), uint64(arr[2]), uint64(arr[3])}}, nil +} + +func scalePositiveFloat64(v float64, prec, scale int32) (float64, error) { + var pscale float64 + if scale >= -76 && scale <= 76 { + pscale = float64PowersOfTen[scale+76] + } else { + pscale = math.Pow10(int(scale)) + } + + v *= pscale + v = math.RoundToEven(v) + maxabs := float64PowersOfTen[prec+76] + if v <= -maxabs || v >= maxabs { + return 0, fmt.Errorf("cannot convert %f to decimal256(precision=%d, scale=%d): overflow", + v, prec, scale) + } + return v, nil +} + +func fromPositiveFloat64(v float64, prec, scale int32) (Num, error) { + val, err := scalePositiveFloat64(v, prec, scale) + if err != nil { + return Num{}, err + } + + var arr [4]float64 + arr[3] = math.Floor(math.Ldexp(val, -192)) + val -= math.Ldexp(arr[3], 192) + arr[2] = math.Floor(math.Ldexp(val, -128)) + val -= math.Ldexp(arr[2], 128) + arr[1] = math.Floor(math.Ldexp(val, -64)) + val -= math.Ldexp(arr[1], 64) + arr[0] = val + + debug.Assert(arr[3] >= 0, "bad conversion float64 to decimal256") + debug.Assert(arr[3] < 1.8446744073709552e+19, "bad conversion float64 to decimal256") // 2**64 + debug.Assert(arr[2] >= 0, "bad conversion float64 to decimal256") + debug.Assert(arr[2] < 1.8446744073709552e+19, "bad conversion float64 to decimal256") // 2**64 + debug.Assert(arr[1] >= 0, "bad conversion float64 to decimal256") + debug.Assert(arr[1] < 1.8446744073709552e+19, "bad conversion float64 to decimal256") // 2**64 + debug.Assert(arr[0] >= 0, "bad conversion float64 to decimal256") + debug.Assert(arr[0] < 1.8446744073709552e+19, "bad conversion float64 to decimal256") // 2**64 + return Num{[4]uint64{uint64(arr[0]), uint64(arr[1]), uint64(arr[2]), uint64(arr[3])}}, nil +} + +func (n Num) tofloat64Positive(scale int32) float64 { + const ( + twoTo64 float64 = 1.8446744073709552e+19 + twoTo128 float64 = 3.402823669209385e+38 + twoTo192 float64 = 6.277101735386681e+57 + ) + + x := float64(n.arr[3]) * twoTo192 + x += float64(n.arr[2]) * twoTo128 + x += float64(n.arr[1]) * twoTo64 + x += float64(n.arr[0]) + + if scale >= -76 && scale <= 76 { + return x * float64PowersOfTen[-scale+76] + } + + return x * math.Pow10(-int(scale)) +} + +func (n Num) ToFloat32(scale int32) float32 { return float32(n.ToFloat64(scale)) } + +func (n Num) ToFloat64(scale int32) float64 { + if n.Sign() < 0 { + return -n.Negate().tofloat64Positive(scale) + } + return n.tofloat64Positive(scale) +} + +func (n Num) Sign() int { + if n == (Num{}) { + return 0 + } + return int(1 | (int64(n.arr[3]) >> 63)) +} + +func FromBigInt(v *big.Int) (n Num) { + bitlen := v.BitLen() + if bitlen > 255 { + panic("arrow/decimal256: cannot represent value larger than 256bits") + } else if bitlen == 0 { + return + } + + b := v.Bits() + for i, bits := range b { + n.arr[i] = uint64(bits) + } + if v.Sign() < 0 { + return n.Negate() + } + return +} + +func toBigIntPositive(n Num) *big.Int { + return new(big.Int).SetBits([]big.Word{big.Word(n.arr[0]), big.Word(n.arr[1]), big.Word(n.arr[2]), big.Word(n.arr[3])}) +} + +func (n Num) BigInt() *big.Int { + if n.Sign() < 0 { + b := toBigIntPositive(n.Negate()) + return b.Neg(b) + } + return toBigIntPositive(n) +} + +// Greater returns true if the value represented by n is > other +func (n Num) Greater(other Num) bool { + return other.Less(n) +} + +// GreaterEqual returns true if the value represented by n is >= other +func (n Num) GreaterEqual(other Num) bool { + return !n.Less(other) +} + +// Less returns true if the value represented by n is < other +func (n Num) Less(other Num) bool { + switch { + case n.arr[3] != other.arr[3]: + return int64(n.arr[3]) < int64(other.arr[3]) + case n.arr[2] != other.arr[2]: + return n.arr[2] < other.arr[2] + case n.arr[1] != other.arr[1]: + return n.arr[1] < other.arr[1] + } + return n.arr[0] < other.arr[0] +} + +// LessEqual returns true if the value represented by n is <= other +func (n Num) LessEqual(other Num) bool { + return !n.Greater(other) +} + +// Max returns the largest Decimal256 that was passed in the arguments +func Max(first Num, rest ...Num) Num { + answer := first + for _, number := range rest { + if number.Greater(answer) { + answer = number + } + } + return answer +} + +// Min returns the smallest Decimal256 that was passed in the arguments +func Min(first Num, rest ...Num) Num { + answer := first + for _, number := range rest { + if number.Less(answer) { + answer = number + } + } + return answer +} + +// Cmp compares the numbers represented by n and other and returns: +// +// +1 if n > other +// 0 if n == other +// -1 if n < other +func (n Num) Cmp(other Num) int { + switch { + case n.Greater(other): + return 1 + case n.Less(other): + return -1 + } + return 0 +} + +func (n Num) IncreaseScaleBy(increase int32) Num { + debug.Assert(increase >= 0, "invalid amount to increase scale by") + debug.Assert(increase <= 76, "invalid amount to increase scale by") + + v := scaleMultipliers[increase].BigInt() + return FromBigInt(v.Mul(n.BigInt(), v)) +} + +func (n Num) ReduceScaleBy(reduce int32, round bool) Num { + debug.Assert(reduce >= 0, "invalid amount to reduce scale by") + debug.Assert(reduce <= 76, "invalid amount to reduce scale by") + + if reduce == 0 { + return n + } + + divisor := scaleMultipliers[reduce].BigInt() + result, remainder := divisor.QuoRem(n.BigInt(), divisor, new(big.Int)) + if round { + divisorHalf := scaleMultipliersHalf[reduce] + if remainder.Abs(remainder).Cmp(divisorHalf.BigInt()) != -1 { + result.Add(result, big.NewInt(int64(n.Sign()))) + } + } + return FromBigInt(result) +} + +func (n Num) rescaleWouldCauseDataLoss(deltaScale int32, multiplier Num) (out Num, loss bool) { + if deltaScale < 0 { + var remainder Num + out, remainder = n.Div(multiplier) + return out, remainder != Num{} + } + + out = n.Mul(multiplier) + if n.Sign() < 0 { + loss = n.Less(out) + } else { + loss = out.Less(n) + } + return +} + +func (n Num) Rescale(original, newscale int32) (out Num, err error) { + if original == newscale { + return n, nil + } + + deltaScale := newscale - original + absDeltaScale := int32(math.Abs(float64(deltaScale))) + + multiplier := scaleMultipliers[absDeltaScale] + var wouldHaveLoss bool + out, wouldHaveLoss = n.rescaleWouldCauseDataLoss(deltaScale, multiplier) + if wouldHaveLoss { + err = errors.New("rescale data loss") + } + return +} + +func (n Num) Abs() Num { + switch n.Sign() { + case -1: + return n.Negate() + } + return n +} + +func (n Num) FitsInPrecision(prec int32) bool { + debug.Assert(prec > 0, "precision must be > 0") + debug.Assert(prec <= 76, "precision must be <= 76") + return n.Abs().Less(scaleMultipliers[prec]) +} + +func (n Num) ToString(scale int32) string { + f := (&big.Float{}).SetInt(n.BigInt()) + f.Quo(f, (&big.Float{}).SetInt(scaleMultipliers[scale].BigInt())) + return f.Text('f', int(scale)) +} + +func GetScaleMultiplier(pow int) Num { return scaleMultipliers[pow] } + +func GetHalfScaleMultiplier(pow int) Num { return scaleMultipliersHalf[pow] } + +var ( + scaleMultipliers = [...]Num{ + FromU64(1), + FromU64(10), + FromU64(100), + FromU64(1000), + FromU64(10000), + FromU64(100000), + FromU64(1000000), + FromU64(10000000), + FromU64(100000000), + FromU64(1000000000), + FromU64(10000000000), + FromU64(100000000000), + FromU64(1000000000000), + FromU64(10000000000000), + FromU64(100000000000000), + FromU64(1000000000000000), + FromU64(10000000000000000), + FromU64(100000000000000000), + FromU64(1000000000000000000), + New(0, 0, 0, 10000000000000000000), + New(0, 0, 5, 7766279631452241920), + New(0, 0, 54, 3875820019684212736), + New(0, 0, 542, 1864712049423024128), + New(0, 0, 5421, 200376420520689664), + New(0, 0, 54210, 2003764205206896640), + New(0, 0, 542101, 1590897978359414784), + New(0, 0, 5421010, 15908979783594147840), + New(0, 0, 54210108, 11515845246265065472), + New(0, 0, 542101086, 4477988020393345024), + New(0, 0, 5421010862, 7886392056514347008), + New(0, 0, 54210108624, 5076944270305263616), + New(0, 0, 542101086242, 13875954555633532928), + New(0, 0, 5421010862427, 9632337040368467968), + New(0, 0, 54210108624275, 4089650035136921600), + New(0, 0, 542101086242752, 4003012203950112768), + New(0, 0, 5421010862427522, 3136633892082024448), + New(0, 0, 54210108624275221, 12919594847110692864), + New(0, 0, 542101086242752217, 68739955140067328), + New(0, 0, 5421010862427522170, 687399551400673280), + New(0, 2, 17316620476856118468, 6873995514006732800), + New(0, 29, 7145508105175220139, 13399722918938673152), + New(0, 293, 16114848830623546549, 4870020673419870208), + New(0, 2938, 13574535716559052564, 11806718586779598848), + New(0, 29387, 6618148649623664334, 7386721425538678784), + New(0, 293873, 10841254275107988496, 80237960548581376), + New(0, 2938735, 16178822382532126880, 802379605485813760), + New(0, 29387358, 14214271235644855872, 8023796054858137600), + New(0, 293873587, 13015503840481697412, 6450984253743169536), + New(0, 2938735877, 1027829888850112811, 9169610316303040512), + New(0, 29387358770, 10278298888501128114, 17909126868192198656), + New(0, 293873587705, 10549268516463523069, 13070572018536022016), + New(0, 2938735877055, 13258964796087472617, 1578511669393358848), + New(0, 29387358770557, 3462439444907864858, 15785116693933588480), + New(0, 293873587705571, 16177650375369096972, 10277214349659471872), + New(0, 2938735877055718, 14202551164014556797, 10538423128046960640), + New(0, 29387358770557187, 12898303124178706663, 13150510911921848320), + New(0, 293873587705571876, 18302566799529756941, 2377900603251621888), + New(0, 2938735877055718769, 17004971331911604867, 5332261958806667264), + New(1, 10940614696847636083, 4029016655730084128, 16429131440647569408), + New(15, 17172426599928602752, 3396678409881738056, 16717361816799281152), + New(159, 5703569335900062977, 15520040025107828953, 1152921504606846976), + New(1593, 1695461137871974930, 7626447661401876602, 11529215046068469760), + New(15930, 16954611378719749304, 2477500319180559562, 4611686018427387904), + New(159309, 3525417123811528497, 6328259118096044006, 9223372036854775808), + New(1593091, 16807427164405733357, 7942358959831785217, 0), + New(15930919, 2053574980671369030, 5636613303479645706, 0), + New(159309191, 2089005733004138687, 1025900813667802212, 0), + New(1593091911, 2443313256331835254, 10259008136678022120, 0), + New(15930919111, 5986388489608800929, 10356360998232463120, 0), + New(159309191113, 4523652674959354447, 11329889613776873120, 0), + New(1593091911132, 8343038602174441244, 2618431695511421504, 0), + New(15930919111324, 9643409726906205977, 7737572881404663424, 0), + New(159309191113245, 4200376900514301694, 3588752519208427776, 0), + New(1593091911132452, 5110280857723913709, 17440781118374726144, 0), + New(15930919111324522, 14209320429820033867, 8387114520361296896, 0), + New(159309191113245227, 12965995782233477362, 10084168908774762496, 0), + New(1593091911132452277, 532749306367912313, 8607968719199866880, 0), + } + + scaleMultipliersHalf = [...]Num{ + FromU64(0), + FromU64(5), + FromU64(50), + FromU64(500), + FromU64(5000), + FromU64(50000), + FromU64(500000), + FromU64(5000000), + FromU64(50000000), + FromU64(500000000), + FromU64(5000000000), + FromU64(50000000000), + FromU64(500000000000), + FromU64(5000000000000), + FromU64(50000000000000), + FromU64(500000000000000), + FromU64(5000000000000000), + FromU64(50000000000000000), + FromU64(500000000000000000), + FromU64(5000000000000000000), + New(0, 0, 2, 13106511852580896768), + New(0, 0, 27, 1937910009842106368), + New(0, 0, 271, 932356024711512064), + New(0, 0, 2710, 9323560247115120640), + New(0, 0, 27105, 1001882102603448320), + New(0, 0, 271050, 10018821026034483200), + New(0, 0, 2710505, 7954489891797073920), + New(0, 0, 27105054, 5757922623132532736), + New(0, 0, 271050543, 2238994010196672512), + New(0, 0, 2710505431, 3943196028257173504), + New(0, 0, 27105054312, 2538472135152631808), + New(0, 0, 271050543121, 6937977277816766464), + New(0, 0, 2710505431213, 14039540557039009792), + New(0, 0, 27105054312137, 11268197054423236608), + New(0, 0, 271050543121376, 2001506101975056384), + New(0, 0, 2710505431213761, 1568316946041012224), + New(0, 0, 27105054312137610, 15683169460410122240), + New(0, 0, 271050543121376108, 9257742014424809472), + New(0, 0, 2710505431213761085, 343699775700336640), + New(0, 1, 8658310238428059234, 3436997757003366400), + New(0, 14, 12796126089442385877, 15923233496324112384), + New(0, 146, 17280796452166549082, 11658382373564710912), + New(0, 1469, 6787267858279526282, 5903359293389799424), + New(0, 14693, 12532446361666607975, 3693360712769339392), + New(0, 146936, 14643999174408770056, 40118980274290688), + New(0, 1469367, 17312783228120839248, 401189802742906880), + New(0, 14693679, 7107135617822427936, 4011898027429068800), + New(0, 146936793, 15731123957095624514, 3225492126871584768), + New(0, 1469367938, 9737286981279832213, 13808177195006296064), + New(0, 14693679385, 5139149444250564057, 8954563434096099328), + New(0, 146936793852, 14498006295086537342, 15758658046122786816), + New(0, 1469367938527, 15852854434898512116, 10012627871551455232), + New(0, 14693679385278, 10954591759308708237, 7892558346966794240), + New(0, 146936793852785, 17312197224539324294, 5138607174829735936), + New(0, 1469367938527859, 7101275582007278398, 14492583600878256128), + New(0, 14693679385278593, 15672523598944129139, 15798627492815699968), + New(0, 146936793852785938, 9151283399764878470, 10412322338480586752), + New(0, 1469367938527859384, 17725857702810578241, 11889503016258109440), + New(0, 14693679385278593849, 11237880364719817872, 8214565720323784704), + New(7, 17809585336819077184, 1698339204940869028, 8358680908399640576), + New(79, 12075156704804807296, 16983392049408690284, 9799832789158199296), + New(796, 10071102605790763273, 3813223830700938301, 5764607523034234880), + New(7965, 8477305689359874652, 1238750159590279781, 2305843009213693952), + New(79654, 10986080598760540056, 12387501595902797811, 4611686018427387904), + New(796545, 17627085619057642486, 13194551516770668416, 9223372036854775808), + New(7965459, 10250159527190460323, 2818306651739822853, 0), + New(79654595, 10267874903356845151, 9736322443688676914, 0), + New(796545955, 10445028665020693435, 5129504068339011060, 0), + New(7965459555, 12216566281659176272, 14401552535971007368, 0), + New(79654595556, 11485198374334453031, 14888316843743212368, 0), + New(796545955566, 4171519301087220622, 1309215847755710752, 0), + New(7965459555662, 4821704863453102988, 13092158477557107520, 0), + New(79654595556622, 11323560487111926655, 1794376259604213888, 0), + New(796545955566226, 2555140428861956854, 17943762596042138880, 0), + New(7965459555662261, 7104660214910016933, 13416929297035424256, 0), + New(79654595556622613, 15706369927971514489, 5042084454387381248, 0), + New(796545955566226138, 9489746690038731964, 13527356396454709248, 0), + } + + float64PowersOfTen = [...]float64{ + 1e-76, 1e-75, 1e-74, 1e-73, 1e-72, 1e-71, 1e-70, 1e-69, 1e-68, 1e-67, 1e-66, 1e-65, + 1e-64, 1e-63, 1e-62, 1e-61, 1e-60, 1e-59, 1e-58, 1e-57, 1e-56, 1e-55, 1e-54, 1e-53, + 1e-52, 1e-51, 1e-50, 1e-49, 1e-48, 1e-47, 1e-46, 1e-45, 1e-44, 1e-43, 1e-42, 1e-41, + 1e-40, 1e-39, 1e-38, 1e-37, 1e-36, 1e-35, 1e-34, 1e-33, 1e-32, 1e-31, 1e-30, 1e-29, + 1e-28, 1e-27, 1e-26, 1e-25, 1e-24, 1e-23, 1e-22, 1e-21, 1e-20, 1e-19, 1e-18, 1e-17, + 1e-16, 1e-15, 1e-14, 1e-13, 1e-12, 1e-11, 1e-10, 1e-9, 1e-8, 1e-7, 1e-6, 1e-5, + 1e-4, 1e-3, 1e-2, 1e-1, 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, + 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, + 1e20, 1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29, 1e30, 1e31, + 1e32, 1e33, 1e34, 1e35, 1e36, 1e37, 1e38, 1e39, 1e40, 1e41, 1e42, 1e43, + 1e44, 1e45, 1e46, 1e47, 1e48, 1e49, 1e50, 1e51, 1e52, 1e53, 1e54, 1e55, + 1e56, 1e57, 1e58, 1e59, 1e60, 1e61, 1e62, 1e63, 1e64, 1e65, 1e66, 1e67, + 1e68, 1e69, 1e70, 1e71, 1e72, 1e73, 1e74, 1e75, 1e76, + } +) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/doc.go b/vendor/github.com/apache/arrow/go/v14/arrow/doc.go new file mode 100644 index 000000000..e923d05d6 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/doc.go @@ -0,0 +1,48 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/* +Package arrow provides an implementation of Apache Arrow. + +Apache Arrow is a cross-language development platform for in-memory data. It specifies a standardized +language-independent columnar memory format for flat and hierarchical data, organized for efficient analytic +operations on modern hardware. It also provides computational libraries and zero-copy streaming +messaging and inter-process communication. + +# Basics + +The fundamental data structure in Arrow is an Array, which holds a sequence of values of the same type. An array +consists of memory holding the data and an additional validity bitmap that indicates if the corresponding entry in the +array is valid (not null). If the array has no null entries, it is possible to omit this bitmap. + +# Requirements + +Despite the go.mod stating go1.20, everything is able to be built with go1.19 or higher. + +To build with tinygo include the noasm build tag. +*/ +package arrow + +const PkgVersion = "14.0.2" + +//go:generate go run _tools/tmpl/main.go -i -data=numeric.tmpldata type_traits_numeric.gen.go.tmpl type_traits_numeric.gen_test.go.tmpl array/numeric.gen.go.tmpl array/numericbuilder.gen.go.tmpl array/bufferbuilder_numeric.gen.go.tmpl +//go:generate go run _tools/tmpl/main.go -i -data=datatype_numeric.gen.go.tmpldata datatype_numeric.gen.go.tmpl tensor/numeric.gen.go.tmpl tensor/numeric.gen_test.go.tmpl +//go:generate go run _tools/tmpl/main.go -i -data=scalar/numeric.gen.go.tmpldata scalar/numeric.gen.go.tmpl scalar/numeric.gen_test.go.tmpl +//go:generate go run ./gen-flatbuffers.go + +// stringer +//go:generate stringer -type=Type +//go:generate stringer -type=UnionMode -linecomment diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/encoded/ree_utils.go b/vendor/github.com/apache/arrow/go/v14/arrow/encoded/ree_utils.go new file mode 100644 index 000000000..1f71e7b52 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/encoded/ree_utils.go @@ -0,0 +1,219 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package encoded + +import ( + "math" + "sort" + + "github.com/apache/arrow/go/v14/arrow" +) + +// FindPhysicalIndex performs a binary search on the run-ends to return +// the appropriate physical offset into the values/run-ends that corresponds +// with the logical index provided when called. If the array's logical offset +// is provided, this is equivalent to calling FindPhysicalOffset. +// +// For example, an array with run-ends [10, 20, 30, 40, 50] and a logicalIdx +// of 25 will return the value 2. This returns the smallest offset +// whose run-end is greater than the logicalIdx requested, which would +// also be the index into the values that contains the correct value. +// +// This function assumes it receives Run End Encoded array data +func FindPhysicalIndex(arr arrow.ArrayData, logicalIdx int) int { + data := arr.Children()[0] + if data.Len() == 0 { + return 0 + } + + switch data.DataType().ID() { + case arrow.INT16: + runEnds := arrow.Int16Traits.CastFromBytes(data.Buffers()[1].Bytes()) + runEnds = runEnds[data.Offset() : data.Offset()+data.Len()] + return sort.Search(len(runEnds), func(i int) bool { return runEnds[i] > int16(logicalIdx) }) + case arrow.INT32: + runEnds := arrow.Int32Traits.CastFromBytes(data.Buffers()[1].Bytes()) + runEnds = runEnds[data.Offset() : data.Offset()+data.Len()] + return sort.Search(len(runEnds), func(i int) bool { return runEnds[i] > int32(logicalIdx) }) + case arrow.INT64: + runEnds := arrow.Int64Traits.CastFromBytes(data.Buffers()[1].Bytes()) + runEnds = runEnds[data.Offset() : data.Offset()+data.Len()] + return sort.Search(len(runEnds), func(i int) bool { return runEnds[i] > int64(logicalIdx) }) + default: + panic("only int16, int32, and int64 are allowed for the run-ends") + } +} + +// FindPhysicalOffset performs a binary search on the run-ends to return +// the appropriate physical offset into the values/run-ends that corresponds +// with the logical offset defined in the array. +// +// For example, an array with run-ends [10, 20, 30, 40, 50] and a logical +// offset of 25 will return the value 2. This returns the smallest offset +// whose run-end is greater than the logical offset, which would also be the +// offset index into the values that contains the correct value. +// +// This function assumes it receives Run End Encoded array data +func FindPhysicalOffset(arr arrow.ArrayData) int { + return FindPhysicalIndex(arr, arr.Offset()) +} + +// GetPhysicalLength returns the physical number of values which are in +// the passed in RunEndEncoded array data. This will take into account +// the offset and length of the array as reported in the array data +// (so that it properly handles slices). +// +// This function assumes it receives Run End Encoded array data +func GetPhysicalLength(arr arrow.ArrayData) int { + if arr.Len() == 0 { + return 0 + } + + data := arr.Children()[0] + physicalOffset := FindPhysicalOffset(arr) + start, length := data.Offset()+physicalOffset, data.Len()-physicalOffset + offset := arr.Offset() + arr.Len() - 1 + + switch data.DataType().ID() { + case arrow.INT16: + runEnds := arrow.Int16Traits.CastFromBytes(data.Buffers()[1].Bytes()) + runEnds = runEnds[start : start+length] + return sort.Search(len(runEnds), func(i int) bool { return runEnds[i] > int16(offset) }) + 1 + case arrow.INT32: + runEnds := arrow.Int32Traits.CastFromBytes(data.Buffers()[1].Bytes()) + runEnds = runEnds[start : start+length] + return sort.Search(len(runEnds), func(i int) bool { return runEnds[i] > int32(offset) }) + 1 + case arrow.INT64: + runEnds := arrow.Int64Traits.CastFromBytes(data.Buffers()[1].Bytes()) + runEnds = runEnds[start : start+length] + return sort.Search(len(runEnds), func(i int) bool { return runEnds[i] > int64(offset) }) + 1 + default: + panic("arrow/rle: can only get rle.PhysicalLength for int16/int32/int64 run ends array") + } +} + +func getRunEnds(arr arrow.ArrayData) func(int64) int64 { + switch arr.DataType().ID() { + case arrow.INT16: + runEnds := arrow.Int16Traits.CastFromBytes(arr.Buffers()[1].Bytes()) + runEnds = runEnds[arr.Offset() : arr.Offset()+arr.Len()] + return func(i int64) int64 { return int64(runEnds[i]) } + case arrow.INT32: + runEnds := arrow.Int32Traits.CastFromBytes(arr.Buffers()[1].Bytes()) + runEnds = runEnds[arr.Offset() : arr.Offset()+arr.Len()] + return func(i int64) int64 { return int64(runEnds[i]) } + case arrow.INT64: + runEnds := arrow.Int64Traits.CastFromBytes(arr.Buffers()[1].Bytes()) + runEnds = runEnds[arr.Offset() : arr.Offset()+arr.Len()] + return func(i int64) int64 { return int64(runEnds[i]) } + default: + panic("only int16, int32, and int64 are allowed for the run-ends") + } +} + +// MergedRuns is used to take two Run End Encoded arrays and iterate +// them, finding the correct physical indices to correspond with the +// runs. +type MergedRuns struct { + inputs [2]arrow.Array + runIndex [2]int64 + inputRunEnds [2]func(int64) int64 + runEnds [2]int64 + logicalLen int + logicalPos int + mergedEnd int64 +} + +// NewMergedRuns takes two RunEndEncoded arrays and returns a MergedRuns +// object that will allow iterating over the physical indices of the runs. +func NewMergedRuns(inputs [2]arrow.Array) *MergedRuns { + if len(inputs) == 0 { + return &MergedRuns{logicalLen: 0} + } + + mr := &MergedRuns{inputs: inputs, logicalLen: inputs[0].Len()} + for i, in := range inputs { + if in.DataType().ID() != arrow.RUN_END_ENCODED { + panic("arrow/rle: NewMergedRuns can only be called with RunLengthEncoded arrays") + } + if in.Len() != mr.logicalLen { + panic("arrow/rle: can only merge runs of RLE arrays of the same length") + } + + mr.inputRunEnds[i] = getRunEnds(in.Data().Children()[0]) + // initialize the runIndex at the physical offset - 1 so the first + // call to Next will increment it to the correct initial offset + // since the initial state is logicalPos == 0 and mergedEnd == 0 + mr.runIndex[i] = int64(FindPhysicalOffset(in.Data())) - 1 + } + + return mr +} + +// Next returns true if there are more values/runs to iterate and false +// when one of the arrays has reached the end. +func (mr *MergedRuns) Next() bool { + mr.logicalPos = int(mr.mergedEnd) + if mr.isEnd() { + return false + } + + for i := range mr.inputs { + if mr.logicalPos == int(mr.runEnds[i]) { + mr.runIndex[i]++ + } + } + mr.findMergedRun() + + return true +} + +// IndexIntoBuffer returns the physical index into the value buffer of +// the passed in array index (ie: 0 for the first array and 1 for the second) +// this takes into account the offset of the array so it is the true physical +// index into the value *buffer* in the child. +func (mr *MergedRuns) IndexIntoBuffer(id int) int64 { + return mr.runIndex[id] + int64(mr.inputs[id].Data().Children()[1].Offset()) +} + +// IndexIntoArray is like IndexIntoBuffer but it doesn't take into account +// the array offset and instead is the index that can be used with the .Value +// method on the array to get the correct value. +func (mr *MergedRuns) IndexIntoArray(id int) int64 { return mr.runIndex[id] } + +// RunLength returns the logical length of the current merged run being looked at. +func (mr *MergedRuns) RunLength() int64 { return mr.mergedEnd - int64(mr.logicalPos) } + +// AccumulatedRunLength returns the logical run end of the current merged run. +func (mr *MergedRuns) AccumulatedRunLength() int64 { return mr.mergedEnd } + +func (mr *MergedRuns) findMergedRun() { + mr.mergedEnd = int64(math.MaxInt64) + for i, in := range mr.inputs { + // logical indices of the end of the run we are currently in each input + mr.runEnds[i] = int64(mr.inputRunEnds[i](mr.runIndex[i]) - int64(in.Data().Offset())) + // the logical length may end in the middle of a run, in case the array was sliced + if mr.logicalLen < int(mr.runEnds[i]) { + mr.runEnds[i] = int64(mr.logicalLen) + } + if mr.runEnds[i] < mr.mergedEnd { + mr.mergedEnd = mr.runEnds[i] + } + } +} + +func (mr *MergedRuns) isEnd() bool { return mr.logicalPos == mr.logicalLen } diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/endian/big.go b/vendor/github.com/apache/arrow/go/v14/arrow/endian/big.go new file mode 100644 index 000000000..0b9258574 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/endian/big.go @@ -0,0 +1,30 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build s390x +// +build s390x + +package endian + +import "encoding/binary" + +var Native = binary.BigEndian + +const ( + IsBigEndian = true + NativeEndian = BigEndian + NonNativeEndian = LittleEndian +) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/endian/endian.go b/vendor/github.com/apache/arrow/go/v14/arrow/endian/endian.go new file mode 100644 index 000000000..3ecda7b36 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/endian/endian.go @@ -0,0 +1,41 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package endian + +import ( + "github.com/apache/arrow/go/v14/arrow/internal/debug" + "github.com/apache/arrow/go/v14/arrow/internal/flatbuf" +) + +type Endianness flatbuf.Endianness + +const ( + LittleEndian Endianness = Endianness(flatbuf.EndiannessLittle) + BigEndian Endianness = Endianness(flatbuf.EndiannessBig) +) + +func (e Endianness) String() string { + switch e { + case LittleEndian: + return "little" + case BigEndian: + return "big" + default: + debug.Assert(false, "wtf? bad endianness value") + return "???" + } +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/endian/little.go b/vendor/github.com/apache/arrow/go/v14/arrow/endian/little.go new file mode 100644 index 000000000..def1fc64b --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/endian/little.go @@ -0,0 +1,30 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !s390x +// +build !s390x + +package endian + +import "encoding/binary" + +var Native = binary.LittleEndian + +const ( + IsBigEndian = false + NativeEndian = LittleEndian + NonNativeEndian = BigEndian +) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/errors.go b/vendor/github.com/apache/arrow/go/v14/arrow/errors.go new file mode 100644 index 000000000..72e6fd8bf --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/errors.go @@ -0,0 +1,28 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package arrow + +import "errors" + +var ( + ErrInvalid = errors.New("invalid") + ErrNotImplemented = errors.New("not implemented") + ErrType = errors.New("type error") + ErrKey = errors.New("key error") + ErrIndex = errors.New("index error") + ErrNotFound = errors.New("not found") +) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/float16/float16.go b/vendor/github.com/apache/arrow/go/v14/arrow/float16/float16.go new file mode 100644 index 000000000..4e03d13df --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/float16/float16.go @@ -0,0 +1,165 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package float16 + +import ( + "math" + "strconv" +) + +// Num represents a half-precision floating point value (float16) +// stored on 16 bits. +// +// See https://en.wikipedia.org/wiki/Half-precision_floating-point_format for more informations. +type Num struct { + bits uint16 +} + +// New creates a new half-precision floating point value from the provided +// float32 value. +func New(f float32) Num { + b := math.Float32bits(f) + sn := uint16((b >> 31) & 0x1) + exp := (b >> 23) & 0xff + res := int16(exp) - 127 + 15 + fc := uint16(b>>13) & 0x3ff + switch { + case exp == 0: + res = 0 + case exp == 0xff: + res = 0x1f + case res > 0x1e: + res = 0x1f + fc = 0 + case res < 0x01: + res = 0 + fc = 0 + } + return Num{bits: (sn << 15) | uint16(res<<10) | fc} +} + +func (f Num) Float32() float32 { + sn := uint32((f.bits >> 15) & 0x1) + exp := (f.bits >> 10) & 0x1f + res := uint32(exp) + 127 - 15 + fc := uint32(f.bits & 0x3ff) + switch { + case exp == 0: + res = 0 + case exp == 0x1f: + res = 0xff + } + return math.Float32frombits((sn << 31) | (res << 23) | (fc << 13)) +} + +func (n Num) Negate() Num { + return Num{bits: n.bits ^ 0x8000} +} + +func (n Num) Add(rhs Num) Num { + return New(n.Float32() + rhs.Float32()) +} + +func (n Num) Sub(rhs Num) Num { + return New(n.Float32() - rhs.Float32()) +} + +func (n Num) Mul(rhs Num) Num { + return New(n.Float32() * rhs.Float32()) +} + +func (n Num) Div(rhs Num) Num { + return New(n.Float32() / rhs.Float32()) +} + +// Greater returns true if the value represented by n is > other +func (n Num) Greater(other Num) bool { + return n.Float32() > other.Float32() +} + +// GreaterEqual returns true if the value represented by n is >= other +func (n Num) GreaterEqual(other Num) bool { + return n.Float32() >= other.Float32() +} + +// Less returns true if the value represented by n is < other +func (n Num) Less(other Num) bool { + return n.Float32() < other.Float32() +} + +// LessEqual returns true if the value represented by n is <= other +func (n Num) LessEqual(other Num) bool { + return n.Float32() <= other.Float32() +} + +// Max returns the largest Decimal128 that was passed in the arguments +func Max(first Num, rest ...Num) Num { + answer := first + for _, number := range rest { + if number.Greater(answer) { + answer = number + } + } + return answer +} + +// Min returns the smallest Decimal128 that was passed in the arguments +func Min(first Num, rest ...Num) Num { + answer := first + for _, number := range rest { + if number.Less(answer) { + answer = number + } + } + return answer +} + +// Cmp compares the numbers represented by n and other and returns: +// +// +1 if n > other +// 0 if n == other +// -1 if n < other +func (n Num) Cmp(other Num) int { + switch { + case n.Greater(other): + return 1 + case n.Less(other): + return -1 + } + return 0 +} + +func (n Num) Abs() Num { + switch n.Sign() { + case -1: + return n.Negate() + } + return n +} + +func (n Num) Sign() int { + f := n.Float32() + if f > 0 { + return 1 + } else if f == 0 { + return 0 + } + return -1 +} + +func (f Num) Uint16() uint16 { return f.bits } +func (f Num) String() string { return strconv.FormatFloat(float64(f.Float32()), 'g', -1, 32) } diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/debug/assert_off.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/debug/assert_off.go new file mode 100644 index 000000000..52b9a2331 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/debug/assert_off.go @@ -0,0 +1,24 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build !assert + +package debug + +// Assert will panic with msg if cond is false. +// +// msg must be a string, func() string or fmt.Stringer. +func Assert(cond bool, msg interface{}) {} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/debug/assert_on.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/debug/assert_on.go new file mode 100644 index 000000000..2aa5d6ace --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/debug/assert_on.go @@ -0,0 +1,28 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build assert + +package debug + +// Assert will panic with msg if cond is false. +// +// msg must be a string, func() string or fmt.Stringer. +func Assert(cond bool, msg interface{}) { + if !cond { + panic(getStringValue(msg)) + } +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/debug/doc.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/debug/doc.go new file mode 100644 index 000000000..3ee1783ca --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/debug/doc.go @@ -0,0 +1,32 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/* +Package debug provides APIs for conditional runtime assertions and debug logging. + + +Using Assert + +To enable runtime assertions, build with the assert tag. When the assert tag is omitted, +the code for the assertion will be omitted from the binary. + + +Using Log + +To enable runtime debug logs, build with the debug tag. When the debug tag is omitted, +the code for logging will be omitted from the binary. +*/ +package debug diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/debug/log_off.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/debug/log_off.go new file mode 100644 index 000000000..48da8e1ee --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/debug/log_off.go @@ -0,0 +1,21 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build !debug + +package debug + +func Log(interface{}) {} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/debug/log_on.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/debug/log_on.go new file mode 100644 index 000000000..99d0c8ae3 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/debug/log_on.go @@ -0,0 +1,32 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build debug + +package debug + +import ( + "log" + "os" +) + +var ( + debug = log.New(os.Stderr, "[D] ", log.LstdFlags) +) + +func Log(msg interface{}) { + debug.Output(1, getStringValue(msg)) +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/debug/util.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/debug/util.go new file mode 100644 index 000000000..7bd3d5389 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/debug/util.go @@ -0,0 +1,37 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build debug assert + +package debug + +import "fmt" + +func getStringValue(v interface{}) string { + switch a := v.(type) { + case func() string: + return a() + + case string: + return a + + case fmt.Stringer: + return a.String() + + default: + panic(fmt.Sprintf("unexpected type, %t", v)) + } +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/dictutils/dict.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/dictutils/dict.go new file mode 100644 index 000000000..e09a2f4a0 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/dictutils/dict.go @@ -0,0 +1,406 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package dictutils + +import ( + "errors" + "fmt" + "hash/maphash" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/array" + "github.com/apache/arrow/go/v14/arrow/memory" +) + +type Kind int8 + +const ( + KindNew Kind = iota + KindDelta + KindReplacement +) + +type FieldPos struct { + parent *FieldPos + index, depth int32 +} + +func NewFieldPos() FieldPos { return FieldPos{index: -1} } + +func (f *FieldPos) Child(index int32) FieldPos { + return FieldPos{parent: f, index: index, depth: f.depth + 1} +} + +func (f *FieldPos) Path() []int32 { + path := make([]int32, f.depth) + cur := f + for i := f.depth - 1; i >= 0; i-- { + path[i] = int32(cur.index) + cur = cur.parent + } + return path +} + +type Mapper struct { + pathToID map[uint64]int64 + hasher maphash.Hash +} + +func (d *Mapper) NumDicts() int { + unique := make(map[int64]bool) + for _, id := range d.pathToID { + unique[id] = true + } + return len(unique) +} + +func (d *Mapper) AddField(id int64, fieldPath []int32) error { + d.hasher.Write(arrow.Int32Traits.CastToBytes(fieldPath)) + defer d.hasher.Reset() + + sum := d.hasher.Sum64() + if _, ok := d.pathToID[sum]; ok { + return errors.New("field already mapped to id") + } + + d.pathToID[sum] = id + return nil +} + +func (d *Mapper) GetFieldID(fieldPath []int32) (int64, error) { + d.hasher.Write(arrow.Int32Traits.CastToBytes(fieldPath)) + defer d.hasher.Reset() + + id, ok := d.pathToID[d.hasher.Sum64()] + if !ok { + return -1, errors.New("arrow/ipc: dictionary field not found") + } + return id, nil +} + +func (d *Mapper) NumFields() int { + return len(d.pathToID) +} + +func (d *Mapper) InsertPath(pos FieldPos) { + id := len(d.pathToID) + d.hasher.Write(arrow.Int32Traits.CastToBytes(pos.Path())) + + d.pathToID[d.hasher.Sum64()] = int64(id) + d.hasher.Reset() +} + +func (d *Mapper) ImportField(pos FieldPos, field *arrow.Field) { + dt := field.Type + if dt.ID() == arrow.EXTENSION { + dt = dt.(arrow.ExtensionType).StorageType() + } + + if dt.ID() == arrow.DICTIONARY { + d.InsertPath(pos) + // import nested dicts + if nested, ok := dt.(*arrow.DictionaryType).ValueType.(arrow.NestedType); ok { + d.ImportFields(pos, nested.Fields()) + } + return + } + + if nested, ok := dt.(arrow.NestedType); ok { + d.ImportFields(pos, nested.Fields()) + } +} + +func (d *Mapper) ImportFields(pos FieldPos, fields []arrow.Field) { + for i := range fields { + d.ImportField(pos.Child(int32(i)), &fields[i]) + } +} + +func (d *Mapper) ImportSchema(schema *arrow.Schema) { + d.pathToID = make(map[uint64]int64) + d.ImportFields(NewFieldPos(), schema.Fields()) +} + +func hasUnresolvedNestedDict(data arrow.ArrayData) bool { + d := data.(*array.Data) + if d.DataType().ID() == arrow.DICTIONARY { + if d.Dictionary().(*array.Data) == nil { + return true + } + if hasUnresolvedNestedDict(d.Dictionary()) { + return true + } + } + for _, c := range d.Children() { + if hasUnresolvedNestedDict(c) { + return true + } + } + return false +} + +type dictpair struct { + ID int64 + Dict arrow.Array +} + +type dictCollector struct { + dictionaries []dictpair + mapper *Mapper +} + +func (d *dictCollector) visitChildren(pos FieldPos, typ arrow.DataType, arr arrow.Array) error { + for i, c := range arr.Data().Children() { + child := array.MakeFromData(c) + defer child.Release() + if err := d.visit(pos.Child(int32(i)), child); err != nil { + return err + } + } + return nil +} + +func (d *dictCollector) visit(pos FieldPos, arr arrow.Array) error { + dt := arr.DataType() + if dt.ID() == arrow.EXTENSION { + dt = dt.(arrow.ExtensionType).StorageType() + arr = arr.(array.ExtensionArray).Storage() + } + + if dt.ID() == arrow.DICTIONARY { + dictarr := arr.(*array.Dictionary) + dict := dictarr.Dictionary() + + // traverse the dictionary to first gather any nested dictionaries + // so they appear in the output before their respective parents + dictType := dt.(*arrow.DictionaryType) + d.visitChildren(pos, dictType.ValueType, dict) + + id, err := d.mapper.GetFieldID(pos.Path()) + if err != nil { + return err + } + dict.Retain() + d.dictionaries = append(d.dictionaries, dictpair{ID: id, Dict: dict}) + return nil + } + return d.visitChildren(pos, dt, arr) +} + +func (d *dictCollector) collect(batch arrow.Record) error { + var ( + pos = NewFieldPos() + schema = batch.Schema() + ) + d.dictionaries = make([]dictpair, 0, d.mapper.NumFields()) + for i := range schema.Fields() { + if err := d.visit(pos.Child(int32(i)), batch.Column(i)); err != nil { + return err + } + } + return nil +} + +type dictMap map[int64][]arrow.ArrayData +type dictTypeMap map[int64]arrow.DataType + +type Memo struct { + Mapper Mapper + dict2id map[arrow.ArrayData]int64 + + id2type dictTypeMap + id2dict dictMap // map of dictionary ID to dictionary array +} + +func NewMemo() Memo { + return Memo{ + dict2id: make(map[arrow.ArrayData]int64), + id2dict: make(dictMap), + id2type: make(dictTypeMap), + Mapper: Mapper{ + pathToID: make(map[uint64]int64), + }, + } +} + +func (memo *Memo) Len() int { return len(memo.id2dict) } + +func (memo *Memo) Clear() { + for id, v := range memo.id2dict { + delete(memo.id2dict, id) + for _, d := range v { + delete(memo.dict2id, d) + d.Release() + } + } +} + +func (memo *Memo) reify(id int64, mem memory.Allocator) (arrow.ArrayData, error) { + v, ok := memo.id2dict[id] + if !ok { + return nil, fmt.Errorf("arrow/ipc: no dictionaries found for id=%d", id) + } + + if len(v) == 1 { + return v[0], nil + } + + // there are deltas we need to concatenate them with the first dictionary + toCombine := make([]arrow.Array, 0, len(v)) + // NOTE: at this point the dictionary data may not be trusted. it needs to + // be validated as concatenation can crash on invalid or corrupted data. + for _, data := range v { + if hasUnresolvedNestedDict(data) { + return nil, fmt.Errorf("arrow/ipc: delta dict with unresolved nested dictionary not implemented") + } + arr := array.MakeFromData(data) + defer arr.Release() + + toCombine = append(toCombine, arr) + defer data.Release() + } + + combined, err := array.Concatenate(toCombine, mem) + if err != nil { + return nil, err + } + defer combined.Release() + combined.Data().Retain() + + memo.id2dict[id] = []arrow.ArrayData{combined.Data()} + return combined.Data(), nil +} + +func (memo *Memo) Dict(id int64, mem memory.Allocator) (arrow.ArrayData, error) { + return memo.reify(id, mem) +} + +func (memo *Memo) AddType(id int64, typ arrow.DataType) error { + if existing, dup := memo.id2type[id]; dup && !arrow.TypeEqual(existing, typ) { + return fmt.Errorf("arrow/ipc: conflicting dictionary types for id %d", id) + } + + memo.id2type[id] = typ + return nil +} + +func (memo *Memo) Type(id int64) (arrow.DataType, bool) { + t, ok := memo.id2type[id] + return t, ok +} + +// func (memo *dictMemo) ID(v arrow.Array) int64 { +// id, ok := memo.dict2id[v] +// if ok { +// return id +// } + +// v.Retain() +// id = int64(len(memo.dict2id)) +// memo.dict2id[v] = id +// memo.id2dict[id] = v +// return id +// } + +func (memo Memo) HasDict(v arrow.ArrayData) bool { + _, ok := memo.dict2id[v] + return ok +} + +func (memo Memo) HasID(id int64) bool { + _, ok := memo.id2dict[id] + return ok +} + +func (memo *Memo) Add(id int64, v arrow.ArrayData) { + if _, dup := memo.id2dict[id]; dup { + panic(fmt.Errorf("arrow/ipc: duplicate id=%d", id)) + } + v.Retain() + memo.id2dict[id] = []arrow.ArrayData{v} + memo.dict2id[v] = id +} + +func (memo *Memo) AddDelta(id int64, v arrow.ArrayData) { + d, ok := memo.id2dict[id] + if !ok { + panic(fmt.Errorf("arrow/ipc: adding delta to non-existing id=%d", id)) + } + v.Retain() + memo.id2dict[id] = append(d, v) +} + +// AddOrReplace puts the provided dictionary into the memo table. If it +// already exists, then the new data will replace it. Otherwise it is added +// to the memo table. +func (memo *Memo) AddOrReplace(id int64, v arrow.ArrayData) bool { + d, ok := memo.id2dict[id] + if ok { + // replace the dictionary and release any existing ones + for _, dict := range d { + dict.Release() + } + d[0] = v + d = d[:1] + } else { + d = []arrow.ArrayData{v} + } + v.Retain() + memo.id2dict[id] = d + return !ok +} + +func CollectDictionaries(batch arrow.Record, mapper *Mapper) (out []dictpair, err error) { + collector := dictCollector{mapper: mapper} + err = collector.collect(batch) + out = collector.dictionaries + return +} + +func ResolveFieldDict(memo *Memo, data arrow.ArrayData, pos FieldPos, mem memory.Allocator) error { + typ := data.DataType() + if typ.ID() == arrow.EXTENSION { + typ = typ.(arrow.ExtensionType).StorageType() + } + if typ.ID() == arrow.DICTIONARY { + id, err := memo.Mapper.GetFieldID(pos.Path()) + if err != nil { + return err + } + dictData, err := memo.Dict(id, mem) + if err != nil { + return err + } + data.(*array.Data).SetDictionary(dictData) + if err := ResolveFieldDict(memo, dictData, pos, mem); err != nil { + return err + } + } + return ResolveDictionaries(memo, data.Children(), pos, mem) +} + +func ResolveDictionaries(memo *Memo, cols []arrow.ArrayData, parentPos FieldPos, mem memory.Allocator) error { + for i, c := range cols { + if c == nil { + continue + } + if err := ResolveFieldDict(memo, c, parentPos.Child(int32(i)), mem); err != nil { + return err + } + } + return nil +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Binary.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Binary.go new file mode 100644 index 000000000..e8018e74c --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Binary.go @@ -0,0 +1,51 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +/// Opaque binary data +type Binary struct { + _tab flatbuffers.Table +} + +func GetRootAsBinary(buf []byte, offset flatbuffers.UOffsetT) *Binary { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &Binary{} + x.Init(buf, n+offset) + return x +} + +func (rcv *Binary) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *Binary) Table() flatbuffers.Table { + return rcv._tab +} + +func BinaryStart(builder *flatbuffers.Builder) { + builder.StartObject(0) +} +func BinaryEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/BinaryView.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/BinaryView.go new file mode 100644 index 000000000..09ca5e7db --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/BinaryView.go @@ -0,0 +1,57 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +/// Logically the same as Binary, but the internal representation uses a view +/// struct that contains the string length and either the string's entire data +/// inline (for small strings) or an inlined prefix, an index of another buffer, +/// and an offset pointing to a slice in that buffer (for non-small strings). +/// +/// Since it uses a variable number of data buffers, each Field with this type +/// must have a corresponding entry in `variadicBufferCounts`. +type BinaryView struct { + _tab flatbuffers.Table +} + +func GetRootAsBinaryView(buf []byte, offset flatbuffers.UOffsetT) *BinaryView { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &BinaryView{} + x.Init(buf, n+offset) + return x +} + +func (rcv *BinaryView) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *BinaryView) Table() flatbuffers.Table { + return rcv._tab +} + +func BinaryViewStart(builder *flatbuffers.Builder) { + builder.StartObject(0) +} +func BinaryViewEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Block.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Block.go new file mode 100644 index 000000000..57a697b19 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Block.go @@ -0,0 +1,74 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +type Block struct { + _tab flatbuffers.Struct +} + +func (rcv *Block) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *Block) Table() flatbuffers.Table { + return rcv._tab.Table +} + +/// Index to the start of the RecordBlock (note this is past the Message header) +func (rcv *Block) Offset() int64 { + return rcv._tab.GetInt64(rcv._tab.Pos + flatbuffers.UOffsetT(0)) +} +/// Index to the start of the RecordBlock (note this is past the Message header) +func (rcv *Block) MutateOffset(n int64) bool { + return rcv._tab.MutateInt64(rcv._tab.Pos+flatbuffers.UOffsetT(0), n) +} + +/// Length of the metadata +func (rcv *Block) MetaDataLength() int32 { + return rcv._tab.GetInt32(rcv._tab.Pos + flatbuffers.UOffsetT(8)) +} +/// Length of the metadata +func (rcv *Block) MutateMetaDataLength(n int32) bool { + return rcv._tab.MutateInt32(rcv._tab.Pos+flatbuffers.UOffsetT(8), n) +} + +/// Length of the data (this is aligned so there can be a gap between this and +/// the metadata). +func (rcv *Block) BodyLength() int64 { + return rcv._tab.GetInt64(rcv._tab.Pos + flatbuffers.UOffsetT(16)) +} +/// Length of the data (this is aligned so there can be a gap between this and +/// the metadata). +func (rcv *Block) MutateBodyLength(n int64) bool { + return rcv._tab.MutateInt64(rcv._tab.Pos+flatbuffers.UOffsetT(16), n) +} + +func CreateBlock(builder *flatbuffers.Builder, offset int64, metaDataLength int32, bodyLength int64) flatbuffers.UOffsetT { + builder.Prep(8, 24) + builder.PrependInt64(bodyLength) + builder.Pad(4) + builder.PrependInt32(metaDataLength) + builder.PrependInt64(offset) + return builder.Offset() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/BodyCompression.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/BodyCompression.go new file mode 100644 index 000000000..6468e2313 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/BodyCompression.go @@ -0,0 +1,89 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +/// Optional compression for the memory buffers constituting IPC message +/// bodies. Intended for use with RecordBatch but could be used for other +/// message types +type BodyCompression struct { + _tab flatbuffers.Table +} + +func GetRootAsBodyCompression(buf []byte, offset flatbuffers.UOffsetT) *BodyCompression { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &BodyCompression{} + x.Init(buf, n+offset) + return x +} + +func (rcv *BodyCompression) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *BodyCompression) Table() flatbuffers.Table { + return rcv._tab +} + +/// Compressor library. +/// For LZ4_FRAME, each compressed buffer must consist of a single frame. +func (rcv *BodyCompression) Codec() CompressionType { + o := flatbuffers.UOffsetT(rcv._tab.Offset(4)) + if o != 0 { + return CompressionType(rcv._tab.GetInt8(o + rcv._tab.Pos)) + } + return 0 +} + +/// Compressor library. +/// For LZ4_FRAME, each compressed buffer must consist of a single frame. +func (rcv *BodyCompression) MutateCodec(n CompressionType) bool { + return rcv._tab.MutateInt8Slot(4, int8(n)) +} + +/// Indicates the way the record batch body was compressed +func (rcv *BodyCompression) Method() BodyCompressionMethod { + o := flatbuffers.UOffsetT(rcv._tab.Offset(6)) + if o != 0 { + return BodyCompressionMethod(rcv._tab.GetInt8(o + rcv._tab.Pos)) + } + return 0 +} + +/// Indicates the way the record batch body was compressed +func (rcv *BodyCompression) MutateMethod(n BodyCompressionMethod) bool { + return rcv._tab.MutateInt8Slot(6, int8(n)) +} + +func BodyCompressionStart(builder *flatbuffers.Builder) { + builder.StartObject(2) +} +func BodyCompressionAddCodec(builder *flatbuffers.Builder, codec CompressionType) { + builder.PrependInt8Slot(0, int8(codec), 0) +} +func BodyCompressionAddMethod(builder *flatbuffers.Builder, method BodyCompressionMethod) { + builder.PrependInt8Slot(1, int8(method), 0) +} +func BodyCompressionEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/BodyCompressionMethod.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/BodyCompressionMethod.go new file mode 100644 index 000000000..108ab3e07 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/BodyCompressionMethod.go @@ -0,0 +1,52 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import "strconv" + +/// Provided for forward compatibility in case we need to support different +/// strategies for compressing the IPC message body (like whole-body +/// compression rather than buffer-level) in the future +type BodyCompressionMethod int8 + +const ( + /// Each constituent buffer is first compressed with the indicated + /// compressor, and then written with the uncompressed length in the first 8 + /// bytes as a 64-bit little-endian signed integer followed by the compressed + /// buffer bytes (and then padding as required by the protocol). The + /// uncompressed length may be set to -1 to indicate that the data that + /// follows is not compressed, which can be useful for cases where + /// compression does not yield appreciable savings. + BodyCompressionMethodBUFFER BodyCompressionMethod = 0 +) + +var EnumNamesBodyCompressionMethod = map[BodyCompressionMethod]string{ + BodyCompressionMethodBUFFER: "BUFFER", +} + +var EnumValuesBodyCompressionMethod = map[string]BodyCompressionMethod{ + "BUFFER": BodyCompressionMethodBUFFER, +} + +func (v BodyCompressionMethod) String() string { + if s, ok := EnumNamesBodyCompressionMethod[v]; ok { + return s + } + return "BodyCompressionMethod(" + strconv.FormatInt(int64(v), 10) + ")" +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Bool.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Bool.go new file mode 100644 index 000000000..6a4a9d268 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Bool.go @@ -0,0 +1,50 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +type Bool struct { + _tab flatbuffers.Table +} + +func GetRootAsBool(buf []byte, offset flatbuffers.UOffsetT) *Bool { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &Bool{} + x.Init(buf, n+offset) + return x +} + +func (rcv *Bool) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *Bool) Table() flatbuffers.Table { + return rcv._tab +} + +func BoolStart(builder *flatbuffers.Builder) { + builder.StartObject(0) +} +func BoolEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Buffer.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Buffer.go new file mode 100644 index 000000000..eba8d99b2 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Buffer.go @@ -0,0 +1,73 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +/// ---------------------------------------------------------------------- +/// A Buffer represents a single contiguous memory segment +type Buffer struct { + _tab flatbuffers.Struct +} + +func (rcv *Buffer) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *Buffer) Table() flatbuffers.Table { + return rcv._tab.Table +} + +/// The relative offset into the shared memory page where the bytes for this +/// buffer starts +func (rcv *Buffer) Offset() int64 { + return rcv._tab.GetInt64(rcv._tab.Pos + flatbuffers.UOffsetT(0)) +} +/// The relative offset into the shared memory page where the bytes for this +/// buffer starts +func (rcv *Buffer) MutateOffset(n int64) bool { + return rcv._tab.MutateInt64(rcv._tab.Pos+flatbuffers.UOffsetT(0), n) +} + +/// The absolute length (in bytes) of the memory buffer. The memory is found +/// from offset (inclusive) to offset + length (non-inclusive). When building +/// messages using the encapsulated IPC message, padding bytes may be written +/// after a buffer, but such padding bytes do not need to be accounted for in +/// the size here. +func (rcv *Buffer) Length() int64 { + return rcv._tab.GetInt64(rcv._tab.Pos + flatbuffers.UOffsetT(8)) +} +/// The absolute length (in bytes) of the memory buffer. The memory is found +/// from offset (inclusive) to offset + length (non-inclusive). When building +/// messages using the encapsulated IPC message, padding bytes may be written +/// after a buffer, but such padding bytes do not need to be accounted for in +/// the size here. +func (rcv *Buffer) MutateLength(n int64) bool { + return rcv._tab.MutateInt64(rcv._tab.Pos+flatbuffers.UOffsetT(8), n) +} + +func CreateBuffer(builder *flatbuffers.Builder, offset int64, length int64) flatbuffers.UOffsetT { + builder.Prep(8, 16) + builder.PrependInt64(length) + builder.PrependInt64(offset) + return builder.Offset() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/CompressionType.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/CompressionType.go new file mode 100644 index 000000000..96e9df072 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/CompressionType.go @@ -0,0 +1,45 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import "strconv" + +type CompressionType int8 + +const ( + CompressionTypeLZ4_FRAME CompressionType = 0 + CompressionTypeZSTD CompressionType = 1 +) + +var EnumNamesCompressionType = map[CompressionType]string{ + CompressionTypeLZ4_FRAME: "LZ4_FRAME", + CompressionTypeZSTD: "ZSTD", +} + +var EnumValuesCompressionType = map[string]CompressionType{ + "LZ4_FRAME": CompressionTypeLZ4_FRAME, + "ZSTD": CompressionTypeZSTD, +} + +func (v CompressionType) String() string { + if s, ok := EnumNamesCompressionType[v]; ok { + return s + } + return "CompressionType(" + strconv.FormatInt(int64(v), 10) + ")" +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Date.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Date.go new file mode 100644 index 000000000..32983ec54 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Date.go @@ -0,0 +1,71 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +/// Date is either a 32-bit or 64-bit signed integer type representing an +/// elapsed time since UNIX epoch (1970-01-01), stored in either of two units: +/// +/// * Milliseconds (64 bits) indicating UNIX time elapsed since the epoch (no +/// leap seconds), where the values are evenly divisible by 86400000 +/// * Days (32 bits) since the UNIX epoch +type Date struct { + _tab flatbuffers.Table +} + +func GetRootAsDate(buf []byte, offset flatbuffers.UOffsetT) *Date { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &Date{} + x.Init(buf, n+offset) + return x +} + +func (rcv *Date) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *Date) Table() flatbuffers.Table { + return rcv._tab +} + +func (rcv *Date) Unit() DateUnit { + o := flatbuffers.UOffsetT(rcv._tab.Offset(4)) + if o != 0 { + return DateUnit(rcv._tab.GetInt16(o + rcv._tab.Pos)) + } + return 1 +} + +func (rcv *Date) MutateUnit(n DateUnit) bool { + return rcv._tab.MutateInt16Slot(4, int16(n)) +} + +func DateStart(builder *flatbuffers.Builder) { + builder.StartObject(1) +} +func DateAddUnit(builder *flatbuffers.Builder, unit DateUnit) { + builder.PrependInt16Slot(0, int16(unit), 1) +} +func DateEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/DateUnit.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/DateUnit.go new file mode 100644 index 000000000..8a12eec17 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/DateUnit.go @@ -0,0 +1,45 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import "strconv" + +type DateUnit int16 + +const ( + DateUnitDAY DateUnit = 0 + DateUnitMILLISECOND DateUnit = 1 +) + +var EnumNamesDateUnit = map[DateUnit]string{ + DateUnitDAY: "DAY", + DateUnitMILLISECOND: "MILLISECOND", +} + +var EnumValuesDateUnit = map[string]DateUnit{ + "DAY": DateUnitDAY, + "MILLISECOND": DateUnitMILLISECOND, +} + +func (v DateUnit) String() string { + if s, ok := EnumNamesDateUnit[v]; ok { + return s + } + return "DateUnit(" + strconv.FormatInt(int64(v), 10) + ")" +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Decimal.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Decimal.go new file mode 100644 index 000000000..c9de254d1 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Decimal.go @@ -0,0 +1,107 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +/// Exact decimal value represented as an integer value in two's +/// complement. Currently only 128-bit (16-byte) and 256-bit (32-byte) integers +/// are used. The representation uses the endianness indicated +/// in the Schema. +type Decimal struct { + _tab flatbuffers.Table +} + +func GetRootAsDecimal(buf []byte, offset flatbuffers.UOffsetT) *Decimal { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &Decimal{} + x.Init(buf, n+offset) + return x +} + +func (rcv *Decimal) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *Decimal) Table() flatbuffers.Table { + return rcv._tab +} + +/// Total number of decimal digits +func (rcv *Decimal) Precision() int32 { + o := flatbuffers.UOffsetT(rcv._tab.Offset(4)) + if o != 0 { + return rcv._tab.GetInt32(o + rcv._tab.Pos) + } + return 0 +} + +/// Total number of decimal digits +func (rcv *Decimal) MutatePrecision(n int32) bool { + return rcv._tab.MutateInt32Slot(4, n) +} + +/// Number of digits after the decimal point "." +func (rcv *Decimal) Scale() int32 { + o := flatbuffers.UOffsetT(rcv._tab.Offset(6)) + if o != 0 { + return rcv._tab.GetInt32(o + rcv._tab.Pos) + } + return 0 +} + +/// Number of digits after the decimal point "." +func (rcv *Decimal) MutateScale(n int32) bool { + return rcv._tab.MutateInt32Slot(6, n) +} + +/// Number of bits per value. The only accepted widths are 128 and 256. +/// We use bitWidth for consistency with Int::bitWidth. +func (rcv *Decimal) BitWidth() int32 { + o := flatbuffers.UOffsetT(rcv._tab.Offset(8)) + if o != 0 { + return rcv._tab.GetInt32(o + rcv._tab.Pos) + } + return 128 +} + +/// Number of bits per value. The only accepted widths are 128 and 256. +/// We use bitWidth for consistency with Int::bitWidth. +func (rcv *Decimal) MutateBitWidth(n int32) bool { + return rcv._tab.MutateInt32Slot(8, n) +} + +func DecimalStart(builder *flatbuffers.Builder) { + builder.StartObject(3) +} +func DecimalAddPrecision(builder *flatbuffers.Builder, precision int32) { + builder.PrependInt32Slot(0, precision, 0) +} +func DecimalAddScale(builder *flatbuffers.Builder, scale int32) { + builder.PrependInt32Slot(1, scale, 0) +} +func DecimalAddBitWidth(builder *flatbuffers.Builder, bitWidth int32) { + builder.PrependInt32Slot(2, bitWidth, 128) +} +func DecimalEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/DictionaryBatch.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/DictionaryBatch.go new file mode 100644 index 000000000..25b5384e4 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/DictionaryBatch.go @@ -0,0 +1,108 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +/// For sending dictionary encoding information. Any Field can be +/// dictionary-encoded, but in this case none of its children may be +/// dictionary-encoded. +/// There is one vector / column per dictionary, but that vector / column +/// may be spread across multiple dictionary batches by using the isDelta +/// flag +type DictionaryBatch struct { + _tab flatbuffers.Table +} + +func GetRootAsDictionaryBatch(buf []byte, offset flatbuffers.UOffsetT) *DictionaryBatch { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &DictionaryBatch{} + x.Init(buf, n+offset) + return x +} + +func (rcv *DictionaryBatch) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *DictionaryBatch) Table() flatbuffers.Table { + return rcv._tab +} + +func (rcv *DictionaryBatch) Id() int64 { + o := flatbuffers.UOffsetT(rcv._tab.Offset(4)) + if o != 0 { + return rcv._tab.GetInt64(o + rcv._tab.Pos) + } + return 0 +} + +func (rcv *DictionaryBatch) MutateId(n int64) bool { + return rcv._tab.MutateInt64Slot(4, n) +} + +func (rcv *DictionaryBatch) Data(obj *RecordBatch) *RecordBatch { + o := flatbuffers.UOffsetT(rcv._tab.Offset(6)) + if o != 0 { + x := rcv._tab.Indirect(o + rcv._tab.Pos) + if obj == nil { + obj = new(RecordBatch) + } + obj.Init(rcv._tab.Bytes, x) + return obj + } + return nil +} + +/// If isDelta is true the values in the dictionary are to be appended to a +/// dictionary with the indicated id. If isDelta is false this dictionary +/// should replace the existing dictionary. +func (rcv *DictionaryBatch) IsDelta() bool { + o := flatbuffers.UOffsetT(rcv._tab.Offset(8)) + if o != 0 { + return rcv._tab.GetBool(o + rcv._tab.Pos) + } + return false +} + +/// If isDelta is true the values in the dictionary are to be appended to a +/// dictionary with the indicated id. If isDelta is false this dictionary +/// should replace the existing dictionary. +func (rcv *DictionaryBatch) MutateIsDelta(n bool) bool { + return rcv._tab.MutateBoolSlot(8, n) +} + +func DictionaryBatchStart(builder *flatbuffers.Builder) { + builder.StartObject(3) +} +func DictionaryBatchAddId(builder *flatbuffers.Builder, id int64) { + builder.PrependInt64Slot(0, id, 0) +} +func DictionaryBatchAddData(builder *flatbuffers.Builder, data flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(1, flatbuffers.UOffsetT(data), 0) +} +func DictionaryBatchAddIsDelta(builder *flatbuffers.Builder, isDelta bool) { + builder.PrependBoolSlot(2, isDelta, false) +} +func DictionaryBatchEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/DictionaryEncoding.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/DictionaryEncoding.go new file mode 100644 index 000000000..a9b09530b --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/DictionaryEncoding.go @@ -0,0 +1,135 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +type DictionaryEncoding struct { + _tab flatbuffers.Table +} + +func GetRootAsDictionaryEncoding(buf []byte, offset flatbuffers.UOffsetT) *DictionaryEncoding { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &DictionaryEncoding{} + x.Init(buf, n+offset) + return x +} + +func (rcv *DictionaryEncoding) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *DictionaryEncoding) Table() flatbuffers.Table { + return rcv._tab +} + +/// The known dictionary id in the application where this data is used. In +/// the file or streaming formats, the dictionary ids are found in the +/// DictionaryBatch messages +func (rcv *DictionaryEncoding) Id() int64 { + o := flatbuffers.UOffsetT(rcv._tab.Offset(4)) + if o != 0 { + return rcv._tab.GetInt64(o + rcv._tab.Pos) + } + return 0 +} + +/// The known dictionary id in the application where this data is used. In +/// the file or streaming formats, the dictionary ids are found in the +/// DictionaryBatch messages +func (rcv *DictionaryEncoding) MutateId(n int64) bool { + return rcv._tab.MutateInt64Slot(4, n) +} + +/// The dictionary indices are constrained to be non-negative integers. If +/// this field is null, the indices must be signed int32. To maximize +/// cross-language compatibility and performance, implementations are +/// recommended to prefer signed integer types over unsigned integer types +/// and to avoid uint64 indices unless they are required by an application. +func (rcv *DictionaryEncoding) IndexType(obj *Int) *Int { + o := flatbuffers.UOffsetT(rcv._tab.Offset(6)) + if o != 0 { + x := rcv._tab.Indirect(o + rcv._tab.Pos) + if obj == nil { + obj = new(Int) + } + obj.Init(rcv._tab.Bytes, x) + return obj + } + return nil +} + +/// The dictionary indices are constrained to be non-negative integers. If +/// this field is null, the indices must be signed int32. To maximize +/// cross-language compatibility and performance, implementations are +/// recommended to prefer signed integer types over unsigned integer types +/// and to avoid uint64 indices unless they are required by an application. +/// By default, dictionaries are not ordered, or the order does not have +/// semantic meaning. In some statistical, applications, dictionary-encoding +/// is used to represent ordered categorical data, and we provide a way to +/// preserve that metadata here +func (rcv *DictionaryEncoding) IsOrdered() bool { + o := flatbuffers.UOffsetT(rcv._tab.Offset(8)) + if o != 0 { + return rcv._tab.GetBool(o + rcv._tab.Pos) + } + return false +} + +/// By default, dictionaries are not ordered, or the order does not have +/// semantic meaning. In some statistical, applications, dictionary-encoding +/// is used to represent ordered categorical data, and we provide a way to +/// preserve that metadata here +func (rcv *DictionaryEncoding) MutateIsOrdered(n bool) bool { + return rcv._tab.MutateBoolSlot(8, n) +} + +func (rcv *DictionaryEncoding) DictionaryKind() DictionaryKind { + o := flatbuffers.UOffsetT(rcv._tab.Offset(10)) + if o != 0 { + return DictionaryKind(rcv._tab.GetInt16(o + rcv._tab.Pos)) + } + return 0 +} + +func (rcv *DictionaryEncoding) MutateDictionaryKind(n DictionaryKind) bool { + return rcv._tab.MutateInt16Slot(10, int16(n)) +} + +func DictionaryEncodingStart(builder *flatbuffers.Builder) { + builder.StartObject(4) +} +func DictionaryEncodingAddId(builder *flatbuffers.Builder, id int64) { + builder.PrependInt64Slot(0, id, 0) +} +func DictionaryEncodingAddIndexType(builder *flatbuffers.Builder, indexType flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(1, flatbuffers.UOffsetT(indexType), 0) +} +func DictionaryEncodingAddIsOrdered(builder *flatbuffers.Builder, isOrdered bool) { + builder.PrependBoolSlot(2, isOrdered, false) +} +func DictionaryEncodingAddDictionaryKind(builder *flatbuffers.Builder, dictionaryKind DictionaryKind) { + builder.PrependInt16Slot(3, int16(dictionaryKind), 0) +} +func DictionaryEncodingEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/DictionaryKind.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/DictionaryKind.go new file mode 100644 index 000000000..126ba5f7f --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/DictionaryKind.go @@ -0,0 +1,47 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import "strconv" + +/// ---------------------------------------------------------------------- +/// Dictionary encoding metadata +/// Maintained for forwards compatibility, in the future +/// Dictionaries might be explicit maps between integers and values +/// allowing for non-contiguous index values +type DictionaryKind int16 + +const ( + DictionaryKindDenseArray DictionaryKind = 0 +) + +var EnumNamesDictionaryKind = map[DictionaryKind]string{ + DictionaryKindDenseArray: "DenseArray", +} + +var EnumValuesDictionaryKind = map[string]DictionaryKind{ + "DenseArray": DictionaryKindDenseArray, +} + +func (v DictionaryKind) String() string { + if s, ok := EnumNamesDictionaryKind[v]; ok { + return s + } + return "DictionaryKind(" + strconv.FormatInt(int64(v), 10) + ")" +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Duration.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Duration.go new file mode 100644 index 000000000..57b7b2a03 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Duration.go @@ -0,0 +1,65 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +type Duration struct { + _tab flatbuffers.Table +} + +func GetRootAsDuration(buf []byte, offset flatbuffers.UOffsetT) *Duration { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &Duration{} + x.Init(buf, n+offset) + return x +} + +func (rcv *Duration) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *Duration) Table() flatbuffers.Table { + return rcv._tab +} + +func (rcv *Duration) Unit() TimeUnit { + o := flatbuffers.UOffsetT(rcv._tab.Offset(4)) + if o != 0 { + return TimeUnit(rcv._tab.GetInt16(o + rcv._tab.Pos)) + } + return 1 +} + +func (rcv *Duration) MutateUnit(n TimeUnit) bool { + return rcv._tab.MutateInt16Slot(4, int16(n)) +} + +func DurationStart(builder *flatbuffers.Builder) { + builder.StartObject(1) +} +func DurationAddUnit(builder *flatbuffers.Builder, unit TimeUnit) { + builder.PrependInt16Slot(0, int16(unit), 1) +} +func DurationEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Endianness.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Endianness.go new file mode 100644 index 000000000..cefa2ff9c --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Endianness.go @@ -0,0 +1,47 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import "strconv" + +/// ---------------------------------------------------------------------- +/// Endianness of the platform producing the data +type Endianness int16 + +const ( + EndiannessLittle Endianness = 0 + EndiannessBig Endianness = 1 +) + +var EnumNamesEndianness = map[Endianness]string{ + EndiannessLittle: "Little", + EndiannessBig: "Big", +} + +var EnumValuesEndianness = map[string]Endianness{ + "Little": EndiannessLittle, + "Big": EndiannessBig, +} + +func (v Endianness) String() string { + if s, ok := EnumNamesEndianness[v]; ok { + return s + } + return "Endianness(" + strconv.FormatInt(int64(v), 10) + ")" +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Feature.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Feature.go new file mode 100644 index 000000000..ae5a0398b --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Feature.go @@ -0,0 +1,71 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import "strconv" + +/// Represents Arrow Features that might not have full support +/// within implementations. This is intended to be used in +/// two scenarios: +/// 1. A mechanism for readers of Arrow Streams +/// and files to understand that the stream or file makes +/// use of a feature that isn't supported or unknown to +/// the implementation (and therefore can meet the Arrow +/// forward compatibility guarantees). +/// 2. A means of negotiating between a client and server +/// what features a stream is allowed to use. The enums +/// values here are intented to represent higher level +/// features, additional details maybe negotiated +/// with key-value pairs specific to the protocol. +/// +/// Enums added to this list should be assigned power-of-two values +/// to facilitate exchanging and comparing bitmaps for supported +/// features. +type Feature int64 + +const ( + /// Needed to make flatbuffers happy. + FeatureUNUSED Feature = 0 + /// The stream makes use of multiple full dictionaries with the + /// same ID and assumes clients implement dictionary replacement + /// correctly. + FeatureDICTIONARY_REPLACEMENT Feature = 1 + /// The stream makes use of compressed bodies as described + /// in Message.fbs. + FeatureCOMPRESSED_BODY Feature = 2 +) + +var EnumNamesFeature = map[Feature]string{ + FeatureUNUSED: "UNUSED", + FeatureDICTIONARY_REPLACEMENT: "DICTIONARY_REPLACEMENT", + FeatureCOMPRESSED_BODY: "COMPRESSED_BODY", +} + +var EnumValuesFeature = map[string]Feature{ + "UNUSED": FeatureUNUSED, + "DICTIONARY_REPLACEMENT": FeatureDICTIONARY_REPLACEMENT, + "COMPRESSED_BODY": FeatureCOMPRESSED_BODY, +} + +func (v Feature) String() string { + if s, ok := EnumNamesFeature[v]; ok { + return s + } + return "Feature(" + strconv.FormatInt(int64(v), 10) + ")" +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Field.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Field.go new file mode 100644 index 000000000..c03cf2f87 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Field.go @@ -0,0 +1,188 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +/// ---------------------------------------------------------------------- +/// A field represents a named column in a record / row batch or child of a +/// nested type. +type Field struct { + _tab flatbuffers.Table +} + +func GetRootAsField(buf []byte, offset flatbuffers.UOffsetT) *Field { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &Field{} + x.Init(buf, n+offset) + return x +} + +func (rcv *Field) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *Field) Table() flatbuffers.Table { + return rcv._tab +} + +/// Name is not required, in i.e. a List +func (rcv *Field) Name() []byte { + o := flatbuffers.UOffsetT(rcv._tab.Offset(4)) + if o != 0 { + return rcv._tab.ByteVector(o + rcv._tab.Pos) + } + return nil +} + +/// Name is not required, in i.e. a List +/// Whether or not this field can contain nulls. Should be true in general. +func (rcv *Field) Nullable() bool { + o := flatbuffers.UOffsetT(rcv._tab.Offset(6)) + if o != 0 { + return rcv._tab.GetBool(o + rcv._tab.Pos) + } + return false +} + +/// Whether or not this field can contain nulls. Should be true in general. +func (rcv *Field) MutateNullable(n bool) bool { + return rcv._tab.MutateBoolSlot(6, n) +} + +func (rcv *Field) TypeType() Type { + o := flatbuffers.UOffsetT(rcv._tab.Offset(8)) + if o != 0 { + return Type(rcv._tab.GetByte(o + rcv._tab.Pos)) + } + return 0 +} + +func (rcv *Field) MutateTypeType(n Type) bool { + return rcv._tab.MutateByteSlot(8, byte(n)) +} + +/// This is the type of the decoded value if the field is dictionary encoded. +func (rcv *Field) Type(obj *flatbuffers.Table) bool { + o := flatbuffers.UOffsetT(rcv._tab.Offset(10)) + if o != 0 { + rcv._tab.Union(obj, o) + return true + } + return false +} + +/// This is the type of the decoded value if the field is dictionary encoded. +/// Present only if the field is dictionary encoded. +func (rcv *Field) Dictionary(obj *DictionaryEncoding) *DictionaryEncoding { + o := flatbuffers.UOffsetT(rcv._tab.Offset(12)) + if o != 0 { + x := rcv._tab.Indirect(o + rcv._tab.Pos) + if obj == nil { + obj = new(DictionaryEncoding) + } + obj.Init(rcv._tab.Bytes, x) + return obj + } + return nil +} + +/// Present only if the field is dictionary encoded. +/// children apply only to nested data types like Struct, List and Union. For +/// primitive types children will have length 0. +func (rcv *Field) Children(obj *Field, j int) bool { + o := flatbuffers.UOffsetT(rcv._tab.Offset(14)) + if o != 0 { + x := rcv._tab.Vector(o) + x += flatbuffers.UOffsetT(j) * 4 + x = rcv._tab.Indirect(x) + obj.Init(rcv._tab.Bytes, x) + return true + } + return false +} + +func (rcv *Field) ChildrenLength() int { + o := flatbuffers.UOffsetT(rcv._tab.Offset(14)) + if o != 0 { + return rcv._tab.VectorLen(o) + } + return 0 +} + +/// children apply only to nested data types like Struct, List and Union. For +/// primitive types children will have length 0. +/// User-defined metadata +func (rcv *Field) CustomMetadata(obj *KeyValue, j int) bool { + o := flatbuffers.UOffsetT(rcv._tab.Offset(16)) + if o != 0 { + x := rcv._tab.Vector(o) + x += flatbuffers.UOffsetT(j) * 4 + x = rcv._tab.Indirect(x) + obj.Init(rcv._tab.Bytes, x) + return true + } + return false +} + +func (rcv *Field) CustomMetadataLength() int { + o := flatbuffers.UOffsetT(rcv._tab.Offset(16)) + if o != 0 { + return rcv._tab.VectorLen(o) + } + return 0 +} + +/// User-defined metadata +func FieldStart(builder *flatbuffers.Builder) { + builder.StartObject(7) +} +func FieldAddName(builder *flatbuffers.Builder, name flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(name), 0) +} +func FieldAddNullable(builder *flatbuffers.Builder, nullable bool) { + builder.PrependBoolSlot(1, nullable, false) +} +func FieldAddTypeType(builder *flatbuffers.Builder, typeType Type) { + builder.PrependByteSlot(2, byte(typeType), 0) +} +func FieldAddType(builder *flatbuffers.Builder, type_ flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(3, flatbuffers.UOffsetT(type_), 0) +} +func FieldAddDictionary(builder *flatbuffers.Builder, dictionary flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(4, flatbuffers.UOffsetT(dictionary), 0) +} +func FieldAddChildren(builder *flatbuffers.Builder, children flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(5, flatbuffers.UOffsetT(children), 0) +} +func FieldStartChildrenVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT { + return builder.StartVector(4, numElems, 4) +} +func FieldAddCustomMetadata(builder *flatbuffers.Builder, customMetadata flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(6, flatbuffers.UOffsetT(customMetadata), 0) +} +func FieldStartCustomMetadataVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT { + return builder.StartVector(4, numElems, 4) +} +func FieldEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/FieldNode.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/FieldNode.go new file mode 100644 index 000000000..606b30bfe --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/FieldNode.go @@ -0,0 +1,76 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +/// ---------------------------------------------------------------------- +/// Data structures for describing a table row batch (a collection of +/// equal-length Arrow arrays) +/// Metadata about a field at some level of a nested type tree (but not +/// its children). +/// +/// For example, a List with values `[[1, 2, 3], null, [4], [5, 6], null]` +/// would have {length: 5, null_count: 2} for its List node, and {length: 6, +/// null_count: 0} for its Int16 node, as separate FieldNode structs +type FieldNode struct { + _tab flatbuffers.Struct +} + +func (rcv *FieldNode) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *FieldNode) Table() flatbuffers.Table { + return rcv._tab.Table +} + +/// The number of value slots in the Arrow array at this level of a nested +/// tree +func (rcv *FieldNode) Length() int64 { + return rcv._tab.GetInt64(rcv._tab.Pos + flatbuffers.UOffsetT(0)) +} +/// The number of value slots in the Arrow array at this level of a nested +/// tree +func (rcv *FieldNode) MutateLength(n int64) bool { + return rcv._tab.MutateInt64(rcv._tab.Pos+flatbuffers.UOffsetT(0), n) +} + +/// The number of observed nulls. Fields with null_count == 0 may choose not +/// to write their physical validity bitmap out as a materialized buffer, +/// instead setting the length of the bitmap buffer to 0. +func (rcv *FieldNode) NullCount() int64 { + return rcv._tab.GetInt64(rcv._tab.Pos + flatbuffers.UOffsetT(8)) +} +/// The number of observed nulls. Fields with null_count == 0 may choose not +/// to write their physical validity bitmap out as a materialized buffer, +/// instead setting the length of the bitmap buffer to 0. +func (rcv *FieldNode) MutateNullCount(n int64) bool { + return rcv._tab.MutateInt64(rcv._tab.Pos+flatbuffers.UOffsetT(8), n) +} + +func CreateFieldNode(builder *flatbuffers.Builder, length int64, nullCount int64) flatbuffers.UOffsetT { + builder.Prep(8, 16) + builder.PrependInt64(nullCount) + builder.PrependInt64(length) + return builder.Offset() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/FixedSizeBinary.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/FixedSizeBinary.go new file mode 100644 index 000000000..4e660d507 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/FixedSizeBinary.go @@ -0,0 +1,67 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +type FixedSizeBinary struct { + _tab flatbuffers.Table +} + +func GetRootAsFixedSizeBinary(buf []byte, offset flatbuffers.UOffsetT) *FixedSizeBinary { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &FixedSizeBinary{} + x.Init(buf, n+offset) + return x +} + +func (rcv *FixedSizeBinary) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *FixedSizeBinary) Table() flatbuffers.Table { + return rcv._tab +} + +/// Number of bytes per value +func (rcv *FixedSizeBinary) ByteWidth() int32 { + o := flatbuffers.UOffsetT(rcv._tab.Offset(4)) + if o != 0 { + return rcv._tab.GetInt32(o + rcv._tab.Pos) + } + return 0 +} + +/// Number of bytes per value +func (rcv *FixedSizeBinary) MutateByteWidth(n int32) bool { + return rcv._tab.MutateInt32Slot(4, n) +} + +func FixedSizeBinaryStart(builder *flatbuffers.Builder) { + builder.StartObject(1) +} +func FixedSizeBinaryAddByteWidth(builder *flatbuffers.Builder, byteWidth int32) { + builder.PrependInt32Slot(0, byteWidth, 0) +} +func FixedSizeBinaryEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/FixedSizeList.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/FixedSizeList.go new file mode 100644 index 000000000..dabf5cc85 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/FixedSizeList.go @@ -0,0 +1,67 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +type FixedSizeList struct { + _tab flatbuffers.Table +} + +func GetRootAsFixedSizeList(buf []byte, offset flatbuffers.UOffsetT) *FixedSizeList { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &FixedSizeList{} + x.Init(buf, n+offset) + return x +} + +func (rcv *FixedSizeList) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *FixedSizeList) Table() flatbuffers.Table { + return rcv._tab +} + +/// Number of list items per value +func (rcv *FixedSizeList) ListSize() int32 { + o := flatbuffers.UOffsetT(rcv._tab.Offset(4)) + if o != 0 { + return rcv._tab.GetInt32(o + rcv._tab.Pos) + } + return 0 +} + +/// Number of list items per value +func (rcv *FixedSizeList) MutateListSize(n int32) bool { + return rcv._tab.MutateInt32Slot(4, n) +} + +func FixedSizeListStart(builder *flatbuffers.Builder) { + builder.StartObject(1) +} +func FixedSizeListAddListSize(builder *flatbuffers.Builder, listSize int32) { + builder.PrependInt32Slot(0, listSize, 0) +} +func FixedSizeListEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/FloatingPoint.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/FloatingPoint.go new file mode 100644 index 000000000..241d448dc --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/FloatingPoint.go @@ -0,0 +1,65 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +type FloatingPoint struct { + _tab flatbuffers.Table +} + +func GetRootAsFloatingPoint(buf []byte, offset flatbuffers.UOffsetT) *FloatingPoint { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &FloatingPoint{} + x.Init(buf, n+offset) + return x +} + +func (rcv *FloatingPoint) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *FloatingPoint) Table() flatbuffers.Table { + return rcv._tab +} + +func (rcv *FloatingPoint) Precision() Precision { + o := flatbuffers.UOffsetT(rcv._tab.Offset(4)) + if o != 0 { + return Precision(rcv._tab.GetInt16(o + rcv._tab.Pos)) + } + return 0 +} + +func (rcv *FloatingPoint) MutatePrecision(n Precision) bool { + return rcv._tab.MutateInt16Slot(4, int16(n)) +} + +func FloatingPointStart(builder *flatbuffers.Builder) { + builder.StartObject(1) +} +func FloatingPointAddPrecision(builder *flatbuffers.Builder, precision Precision) { + builder.PrependInt16Slot(0, int16(precision), 0) +} +func FloatingPointEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Footer.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Footer.go new file mode 100644 index 000000000..65b0ff095 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Footer.go @@ -0,0 +1,162 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +/// ---------------------------------------------------------------------- +/// Arrow File metadata +/// +type Footer struct { + _tab flatbuffers.Table +} + +func GetRootAsFooter(buf []byte, offset flatbuffers.UOffsetT) *Footer { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &Footer{} + x.Init(buf, n+offset) + return x +} + +func (rcv *Footer) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *Footer) Table() flatbuffers.Table { + return rcv._tab +} + +func (rcv *Footer) Version() MetadataVersion { + o := flatbuffers.UOffsetT(rcv._tab.Offset(4)) + if o != 0 { + return MetadataVersion(rcv._tab.GetInt16(o + rcv._tab.Pos)) + } + return 0 +} + +func (rcv *Footer) MutateVersion(n MetadataVersion) bool { + return rcv._tab.MutateInt16Slot(4, int16(n)) +} + +func (rcv *Footer) Schema(obj *Schema) *Schema { + o := flatbuffers.UOffsetT(rcv._tab.Offset(6)) + if o != 0 { + x := rcv._tab.Indirect(o + rcv._tab.Pos) + if obj == nil { + obj = new(Schema) + } + obj.Init(rcv._tab.Bytes, x) + return obj + } + return nil +} + +func (rcv *Footer) Dictionaries(obj *Block, j int) bool { + o := flatbuffers.UOffsetT(rcv._tab.Offset(8)) + if o != 0 { + x := rcv._tab.Vector(o) + x += flatbuffers.UOffsetT(j) * 24 + obj.Init(rcv._tab.Bytes, x) + return true + } + return false +} + +func (rcv *Footer) DictionariesLength() int { + o := flatbuffers.UOffsetT(rcv._tab.Offset(8)) + if o != 0 { + return rcv._tab.VectorLen(o) + } + return 0 +} + +func (rcv *Footer) RecordBatches(obj *Block, j int) bool { + o := flatbuffers.UOffsetT(rcv._tab.Offset(10)) + if o != 0 { + x := rcv._tab.Vector(o) + x += flatbuffers.UOffsetT(j) * 24 + obj.Init(rcv._tab.Bytes, x) + return true + } + return false +} + +func (rcv *Footer) RecordBatchesLength() int { + o := flatbuffers.UOffsetT(rcv._tab.Offset(10)) + if o != 0 { + return rcv._tab.VectorLen(o) + } + return 0 +} + +/// User-defined metadata +func (rcv *Footer) CustomMetadata(obj *KeyValue, j int) bool { + o := flatbuffers.UOffsetT(rcv._tab.Offset(12)) + if o != 0 { + x := rcv._tab.Vector(o) + x += flatbuffers.UOffsetT(j) * 4 + x = rcv._tab.Indirect(x) + obj.Init(rcv._tab.Bytes, x) + return true + } + return false +} + +func (rcv *Footer) CustomMetadataLength() int { + o := flatbuffers.UOffsetT(rcv._tab.Offset(12)) + if o != 0 { + return rcv._tab.VectorLen(o) + } + return 0 +} + +/// User-defined metadata +func FooterStart(builder *flatbuffers.Builder) { + builder.StartObject(5) +} +func FooterAddVersion(builder *flatbuffers.Builder, version MetadataVersion) { + builder.PrependInt16Slot(0, int16(version), 0) +} +func FooterAddSchema(builder *flatbuffers.Builder, schema flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(1, flatbuffers.UOffsetT(schema), 0) +} +func FooterAddDictionaries(builder *flatbuffers.Builder, dictionaries flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(2, flatbuffers.UOffsetT(dictionaries), 0) +} +func FooterStartDictionariesVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT { + return builder.StartVector(24, numElems, 8) +} +func FooterAddRecordBatches(builder *flatbuffers.Builder, recordBatches flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(3, flatbuffers.UOffsetT(recordBatches), 0) +} +func FooterStartRecordBatchesVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT { + return builder.StartVector(24, numElems, 8) +} +func FooterAddCustomMetadata(builder *flatbuffers.Builder, customMetadata flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(4, flatbuffers.UOffsetT(customMetadata), 0) +} +func FooterStartCustomMetadataVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT { + return builder.StartVector(4, numElems, 4) +} +func FooterEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Int.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Int.go new file mode 100644 index 000000000..9f4b19117 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Int.go @@ -0,0 +1,80 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +type Int struct { + _tab flatbuffers.Table +} + +func GetRootAsInt(buf []byte, offset flatbuffers.UOffsetT) *Int { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &Int{} + x.Init(buf, n+offset) + return x +} + +func (rcv *Int) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *Int) Table() flatbuffers.Table { + return rcv._tab +} + +func (rcv *Int) BitWidth() int32 { + o := flatbuffers.UOffsetT(rcv._tab.Offset(4)) + if o != 0 { + return rcv._tab.GetInt32(o + rcv._tab.Pos) + } + return 0 +} + +func (rcv *Int) MutateBitWidth(n int32) bool { + return rcv._tab.MutateInt32Slot(4, n) +} + +func (rcv *Int) IsSigned() bool { + o := flatbuffers.UOffsetT(rcv._tab.Offset(6)) + if o != 0 { + return rcv._tab.GetBool(o + rcv._tab.Pos) + } + return false +} + +func (rcv *Int) MutateIsSigned(n bool) bool { + return rcv._tab.MutateBoolSlot(6, n) +} + +func IntStart(builder *flatbuffers.Builder) { + builder.StartObject(2) +} +func IntAddBitWidth(builder *flatbuffers.Builder, bitWidth int32) { + builder.PrependInt32Slot(0, bitWidth, 0) +} +func IntAddIsSigned(builder *flatbuffers.Builder, isSigned bool) { + builder.PrependBoolSlot(1, isSigned, false) +} +func IntEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Interval.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Interval.go new file mode 100644 index 000000000..12c56d5c2 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Interval.go @@ -0,0 +1,65 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +type Interval struct { + _tab flatbuffers.Table +} + +func GetRootAsInterval(buf []byte, offset flatbuffers.UOffsetT) *Interval { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &Interval{} + x.Init(buf, n+offset) + return x +} + +func (rcv *Interval) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *Interval) Table() flatbuffers.Table { + return rcv._tab +} + +func (rcv *Interval) Unit() IntervalUnit { + o := flatbuffers.UOffsetT(rcv._tab.Offset(4)) + if o != 0 { + return IntervalUnit(rcv._tab.GetInt16(o + rcv._tab.Pos)) + } + return 0 +} + +func (rcv *Interval) MutateUnit(n IntervalUnit) bool { + return rcv._tab.MutateInt16Slot(4, int16(n)) +} + +func IntervalStart(builder *flatbuffers.Builder) { + builder.StartObject(1) +} +func IntervalAddUnit(builder *flatbuffers.Builder, unit IntervalUnit) { + builder.PrependInt16Slot(0, int16(unit), 0) +} +func IntervalEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/IntervalUnit.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/IntervalUnit.go new file mode 100644 index 000000000..f3ed1ae7b --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/IntervalUnit.go @@ -0,0 +1,48 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import "strconv" + +type IntervalUnit int16 + +const ( + IntervalUnitYEAR_MONTH IntervalUnit = 0 + IntervalUnitDAY_TIME IntervalUnit = 1 + IntervalUnitMONTH_DAY_NANO IntervalUnit = 2 +) + +var EnumNamesIntervalUnit = map[IntervalUnit]string{ + IntervalUnitYEAR_MONTH: "YEAR_MONTH", + IntervalUnitDAY_TIME: "DAY_TIME", + IntervalUnitMONTH_DAY_NANO: "MONTH_DAY_NANO", +} + +var EnumValuesIntervalUnit = map[string]IntervalUnit{ + "YEAR_MONTH": IntervalUnitYEAR_MONTH, + "DAY_TIME": IntervalUnitDAY_TIME, + "MONTH_DAY_NANO": IntervalUnitMONTH_DAY_NANO, +} + +func (v IntervalUnit) String() string { + if s, ok := EnumNamesIntervalUnit[v]; ok { + return s + } + return "IntervalUnit(" + strconv.FormatInt(int64(v), 10) + ")" +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/KeyValue.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/KeyValue.go new file mode 100644 index 000000000..c1b85318e --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/KeyValue.go @@ -0,0 +1,75 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +/// ---------------------------------------------------------------------- +/// user defined key value pairs to add custom metadata to arrow +/// key namespacing is the responsibility of the user +type KeyValue struct { + _tab flatbuffers.Table +} + +func GetRootAsKeyValue(buf []byte, offset flatbuffers.UOffsetT) *KeyValue { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &KeyValue{} + x.Init(buf, n+offset) + return x +} + +func (rcv *KeyValue) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *KeyValue) Table() flatbuffers.Table { + return rcv._tab +} + +func (rcv *KeyValue) Key() []byte { + o := flatbuffers.UOffsetT(rcv._tab.Offset(4)) + if o != 0 { + return rcv._tab.ByteVector(o + rcv._tab.Pos) + } + return nil +} + +func (rcv *KeyValue) Value() []byte { + o := flatbuffers.UOffsetT(rcv._tab.Offset(6)) + if o != 0 { + return rcv._tab.ByteVector(o + rcv._tab.Pos) + } + return nil +} + +func KeyValueStart(builder *flatbuffers.Builder) { + builder.StartObject(2) +} +func KeyValueAddKey(builder *flatbuffers.Builder, key flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(key), 0) +} +func KeyValueAddValue(builder *flatbuffers.Builder, value flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(1, flatbuffers.UOffsetT(value), 0) +} +func KeyValueEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/LargeBinary.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/LargeBinary.go new file mode 100644 index 000000000..2c3befcc1 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/LargeBinary.go @@ -0,0 +1,52 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +/// Same as Binary, but with 64-bit offsets, allowing to represent +/// extremely large data values. +type LargeBinary struct { + _tab flatbuffers.Table +} + +func GetRootAsLargeBinary(buf []byte, offset flatbuffers.UOffsetT) *LargeBinary { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &LargeBinary{} + x.Init(buf, n+offset) + return x +} + +func (rcv *LargeBinary) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *LargeBinary) Table() flatbuffers.Table { + return rcv._tab +} + +func LargeBinaryStart(builder *flatbuffers.Builder) { + builder.StartObject(0) +} +func LargeBinaryEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/LargeList.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/LargeList.go new file mode 100644 index 000000000..92f228458 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/LargeList.go @@ -0,0 +1,52 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +/// Same as List, but with 64-bit offsets, allowing to represent +/// extremely large data values. +type LargeList struct { + _tab flatbuffers.Table +} + +func GetRootAsLargeList(buf []byte, offset flatbuffers.UOffsetT) *LargeList { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &LargeList{} + x.Init(buf, n+offset) + return x +} + +func (rcv *LargeList) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *LargeList) Table() flatbuffers.Table { + return rcv._tab +} + +func LargeListStart(builder *flatbuffers.Builder) { + builder.StartObject(0) +} +func LargeListEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/LargeListView.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/LargeListView.go new file mode 100644 index 000000000..5b1df149c --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/LargeListView.go @@ -0,0 +1,52 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +/// Same as ListView, but with 64-bit offsets and sizes, allowing to represent +/// extremely large data values. +type LargeListView struct { + _tab flatbuffers.Table +} + +func GetRootAsLargeListView(buf []byte, offset flatbuffers.UOffsetT) *LargeListView { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &LargeListView{} + x.Init(buf, n+offset) + return x +} + +func (rcv *LargeListView) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *LargeListView) Table() flatbuffers.Table { + return rcv._tab +} + +func LargeListViewStart(builder *flatbuffers.Builder) { + builder.StartObject(0) +} +func LargeListViewEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/LargeUtf8.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/LargeUtf8.go new file mode 100644 index 000000000..e78b33e11 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/LargeUtf8.go @@ -0,0 +1,52 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +/// Same as Utf8, but with 64-bit offsets, allowing to represent +/// extremely large data values. +type LargeUtf8 struct { + _tab flatbuffers.Table +} + +func GetRootAsLargeUtf8(buf []byte, offset flatbuffers.UOffsetT) *LargeUtf8 { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &LargeUtf8{} + x.Init(buf, n+offset) + return x +} + +func (rcv *LargeUtf8) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *LargeUtf8) Table() flatbuffers.Table { + return rcv._tab +} + +func LargeUtf8Start(builder *flatbuffers.Builder) { + builder.StartObject(0) +} +func LargeUtf8End(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/List.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/List.go new file mode 100644 index 000000000..ba84319d3 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/List.go @@ -0,0 +1,50 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +type List struct { + _tab flatbuffers.Table +} + +func GetRootAsList(buf []byte, offset flatbuffers.UOffsetT) *List { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &List{} + x.Init(buf, n+offset) + return x +} + +func (rcv *List) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *List) Table() flatbuffers.Table { + return rcv._tab +} + +func ListStart(builder *flatbuffers.Builder) { + builder.StartObject(0) +} +func ListEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/ListView.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/ListView.go new file mode 100644 index 000000000..46b1e0b3c --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/ListView.go @@ -0,0 +1,53 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +/// Represents the same logical types that List can, but contains offsets and +/// sizes allowing for writes in any order and sharing of child values among +/// list values. +type ListView struct { + _tab flatbuffers.Table +} + +func GetRootAsListView(buf []byte, offset flatbuffers.UOffsetT) *ListView { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &ListView{} + x.Init(buf, n+offset) + return x +} + +func (rcv *ListView) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *ListView) Table() flatbuffers.Table { + return rcv._tab +} + +func ListViewStart(builder *flatbuffers.Builder) { + builder.StartObject(0) +} +func ListViewEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Map.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Map.go new file mode 100644 index 000000000..8802aba1e --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Map.go @@ -0,0 +1,92 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +/// A Map is a logical nested type that is represented as +/// +/// List> +/// +/// In this layout, the keys and values are each respectively contiguous. We do +/// not constrain the key and value types, so the application is responsible +/// for ensuring that the keys are hashable and unique. Whether the keys are sorted +/// may be set in the metadata for this field. +/// +/// In a field with Map type, the field has a child Struct field, which then +/// has two children: key type and the second the value type. The names of the +/// child fields may be respectively "entries", "key", and "value", but this is +/// not enforced. +/// +/// Map +/// ```text +/// - child[0] entries: Struct +/// - child[0] key: K +/// - child[1] value: V +/// ``` +/// Neither the "entries" field nor the "key" field may be nullable. +/// +/// The metadata is structured so that Arrow systems without special handling +/// for Map can make Map an alias for List. The "layout" attribute for the Map +/// field must have the same contents as a List. +type Map struct { + _tab flatbuffers.Table +} + +func GetRootAsMap(buf []byte, offset flatbuffers.UOffsetT) *Map { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &Map{} + x.Init(buf, n+offset) + return x +} + +func (rcv *Map) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *Map) Table() flatbuffers.Table { + return rcv._tab +} + +/// Set to true if the keys within each value are sorted +func (rcv *Map) KeysSorted() bool { + o := flatbuffers.UOffsetT(rcv._tab.Offset(4)) + if o != 0 { + return rcv._tab.GetBool(o + rcv._tab.Pos) + } + return false +} + +/// Set to true if the keys within each value are sorted +func (rcv *Map) MutateKeysSorted(n bool) bool { + return rcv._tab.MutateBoolSlot(4, n) +} + +func MapStart(builder *flatbuffers.Builder) { + builder.StartObject(1) +} +func MapAddKeysSorted(builder *flatbuffers.Builder, keysSorted bool) { + builder.PrependBoolSlot(0, keysSorted, false) +} +func MapEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Message.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Message.go new file mode 100644 index 000000000..f4b4a0ff8 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Message.go @@ -0,0 +1,133 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +type Message struct { + _tab flatbuffers.Table +} + +func GetRootAsMessage(buf []byte, offset flatbuffers.UOffsetT) *Message { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &Message{} + x.Init(buf, n+offset) + return x +} + +func (rcv *Message) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *Message) Table() flatbuffers.Table { + return rcv._tab +} + +func (rcv *Message) Version() MetadataVersion { + o := flatbuffers.UOffsetT(rcv._tab.Offset(4)) + if o != 0 { + return MetadataVersion(rcv._tab.GetInt16(o + rcv._tab.Pos)) + } + return 0 +} + +func (rcv *Message) MutateVersion(n MetadataVersion) bool { + return rcv._tab.MutateInt16Slot(4, int16(n)) +} + +func (rcv *Message) HeaderType() MessageHeader { + o := flatbuffers.UOffsetT(rcv._tab.Offset(6)) + if o != 0 { + return MessageHeader(rcv._tab.GetByte(o + rcv._tab.Pos)) + } + return 0 +} + +func (rcv *Message) MutateHeaderType(n MessageHeader) bool { + return rcv._tab.MutateByteSlot(6, byte(n)) +} + +func (rcv *Message) Header(obj *flatbuffers.Table) bool { + o := flatbuffers.UOffsetT(rcv._tab.Offset(8)) + if o != 0 { + rcv._tab.Union(obj, o) + return true + } + return false +} + +func (rcv *Message) BodyLength() int64 { + o := flatbuffers.UOffsetT(rcv._tab.Offset(10)) + if o != 0 { + return rcv._tab.GetInt64(o + rcv._tab.Pos) + } + return 0 +} + +func (rcv *Message) MutateBodyLength(n int64) bool { + return rcv._tab.MutateInt64Slot(10, n) +} + +func (rcv *Message) CustomMetadata(obj *KeyValue, j int) bool { + o := flatbuffers.UOffsetT(rcv._tab.Offset(12)) + if o != 0 { + x := rcv._tab.Vector(o) + x += flatbuffers.UOffsetT(j) * 4 + x = rcv._tab.Indirect(x) + obj.Init(rcv._tab.Bytes, x) + return true + } + return false +} + +func (rcv *Message) CustomMetadataLength() int { + o := flatbuffers.UOffsetT(rcv._tab.Offset(12)) + if o != 0 { + return rcv._tab.VectorLen(o) + } + return 0 +} + +func MessageStart(builder *flatbuffers.Builder) { + builder.StartObject(5) +} +func MessageAddVersion(builder *flatbuffers.Builder, version MetadataVersion) { + builder.PrependInt16Slot(0, int16(version), 0) +} +func MessageAddHeaderType(builder *flatbuffers.Builder, headerType MessageHeader) { + builder.PrependByteSlot(1, byte(headerType), 0) +} +func MessageAddHeader(builder *flatbuffers.Builder, header flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(2, flatbuffers.UOffsetT(header), 0) +} +func MessageAddBodyLength(builder *flatbuffers.Builder, bodyLength int64) { + builder.PrependInt64Slot(3, bodyLength, 0) +} +func MessageAddCustomMetadata(builder *flatbuffers.Builder, customMetadata flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(4, flatbuffers.UOffsetT(customMetadata), 0) +} +func MessageStartCustomMetadataVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT { + return builder.StartVector(4, numElems, 4) +} +func MessageEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/MessageHeader.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/MessageHeader.go new file mode 100644 index 000000000..c12fc1058 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/MessageHeader.go @@ -0,0 +1,65 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import "strconv" + +/// ---------------------------------------------------------------------- +/// The root Message type +/// This union enables us to easily send different message types without +/// redundant storage, and in the future we can easily add new message types. +/// +/// Arrow implementations do not need to implement all of the message types, +/// which may include experimental metadata types. For maximum compatibility, +/// it is best to send data using RecordBatch +type MessageHeader byte + +const ( + MessageHeaderNONE MessageHeader = 0 + MessageHeaderSchema MessageHeader = 1 + MessageHeaderDictionaryBatch MessageHeader = 2 + MessageHeaderRecordBatch MessageHeader = 3 + MessageHeaderTensor MessageHeader = 4 + MessageHeaderSparseTensor MessageHeader = 5 +) + +var EnumNamesMessageHeader = map[MessageHeader]string{ + MessageHeaderNONE: "NONE", + MessageHeaderSchema: "Schema", + MessageHeaderDictionaryBatch: "DictionaryBatch", + MessageHeaderRecordBatch: "RecordBatch", + MessageHeaderTensor: "Tensor", + MessageHeaderSparseTensor: "SparseTensor", +} + +var EnumValuesMessageHeader = map[string]MessageHeader{ + "NONE": MessageHeaderNONE, + "Schema": MessageHeaderSchema, + "DictionaryBatch": MessageHeaderDictionaryBatch, + "RecordBatch": MessageHeaderRecordBatch, + "Tensor": MessageHeaderTensor, + "SparseTensor": MessageHeaderSparseTensor, +} + +func (v MessageHeader) String() string { + if s, ok := EnumNamesMessageHeader[v]; ok { + return s + } + return "MessageHeader(" + strconv.FormatInt(int64(v), 10) + ")" +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/MetadataVersion.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/MetadataVersion.go new file mode 100644 index 000000000..21b234f9c --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/MetadataVersion.go @@ -0,0 +1,65 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import "strconv" + +type MetadataVersion int16 + +const ( + /// 0.1.0 (October 2016). + MetadataVersionV1 MetadataVersion = 0 + /// 0.2.0 (February 2017). Non-backwards compatible with V1. + MetadataVersionV2 MetadataVersion = 1 + /// 0.3.0 -> 0.7.1 (May - December 2017). Non-backwards compatible with V2. + MetadataVersionV3 MetadataVersion = 2 + /// >= 0.8.0 (December 2017). Non-backwards compatible with V3. + MetadataVersionV4 MetadataVersion = 3 + /// >= 1.0.0 (July 2020. Backwards compatible with V4 (V5 readers can read V4 + /// metadata and IPC messages). Implementations are recommended to provide a + /// V4 compatibility mode with V5 format changes disabled. + /// + /// Incompatible changes between V4 and V5: + /// - Union buffer layout has changed. In V5, Unions don't have a validity + /// bitmap buffer. + MetadataVersionV5 MetadataVersion = 4 +) + +var EnumNamesMetadataVersion = map[MetadataVersion]string{ + MetadataVersionV1: "V1", + MetadataVersionV2: "V2", + MetadataVersionV3: "V3", + MetadataVersionV4: "V4", + MetadataVersionV5: "V5", +} + +var EnumValuesMetadataVersion = map[string]MetadataVersion{ + "V1": MetadataVersionV1, + "V2": MetadataVersionV2, + "V3": MetadataVersionV3, + "V4": MetadataVersionV4, + "V5": MetadataVersionV5, +} + +func (v MetadataVersion) String() string { + if s, ok := EnumNamesMetadataVersion[v]; ok { + return s + } + return "MetadataVersion(" + strconv.FormatInt(int64(v), 10) + ")" +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Null.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Null.go new file mode 100644 index 000000000..3c3eb4bda --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Null.go @@ -0,0 +1,51 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +/// These are stored in the flatbuffer in the Type union below +type Null struct { + _tab flatbuffers.Table +} + +func GetRootAsNull(buf []byte, offset flatbuffers.UOffsetT) *Null { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &Null{} + x.Init(buf, n+offset) + return x +} + +func (rcv *Null) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *Null) Table() flatbuffers.Table { + return rcv._tab +} + +func NullStart(builder *flatbuffers.Builder) { + builder.StartObject(0) +} +func NullEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Precision.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Precision.go new file mode 100644 index 000000000..d8021ccc4 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Precision.go @@ -0,0 +1,48 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import "strconv" + +type Precision int16 + +const ( + PrecisionHALF Precision = 0 + PrecisionSINGLE Precision = 1 + PrecisionDOUBLE Precision = 2 +) + +var EnumNamesPrecision = map[Precision]string{ + PrecisionHALF: "HALF", + PrecisionSINGLE: "SINGLE", + PrecisionDOUBLE: "DOUBLE", +} + +var EnumValuesPrecision = map[string]Precision{ + "HALF": PrecisionHALF, + "SINGLE": PrecisionSINGLE, + "DOUBLE": PrecisionDOUBLE, +} + +func (v Precision) String() string { + if s, ok := EnumNamesPrecision[v]; ok { + return s + } + return "Precision(" + strconv.FormatInt(int64(v), 10) + ")" +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/RecordBatch.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/RecordBatch.go new file mode 100644 index 000000000..c50f4a6e8 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/RecordBatch.go @@ -0,0 +1,214 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +/// A data header describing the shared memory layout of a "record" or "row" +/// batch. Some systems call this a "row batch" internally and others a "record +/// batch". +type RecordBatch struct { + _tab flatbuffers.Table +} + +func GetRootAsRecordBatch(buf []byte, offset flatbuffers.UOffsetT) *RecordBatch { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &RecordBatch{} + x.Init(buf, n+offset) + return x +} + +func (rcv *RecordBatch) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *RecordBatch) Table() flatbuffers.Table { + return rcv._tab +} + +/// number of records / rows. The arrays in the batch should all have this +/// length +func (rcv *RecordBatch) Length() int64 { + o := flatbuffers.UOffsetT(rcv._tab.Offset(4)) + if o != 0 { + return rcv._tab.GetInt64(o + rcv._tab.Pos) + } + return 0 +} + +/// number of records / rows. The arrays in the batch should all have this +/// length +func (rcv *RecordBatch) MutateLength(n int64) bool { + return rcv._tab.MutateInt64Slot(4, n) +} + +/// Nodes correspond to the pre-ordered flattened logical schema +func (rcv *RecordBatch) Nodes(obj *FieldNode, j int) bool { + o := flatbuffers.UOffsetT(rcv._tab.Offset(6)) + if o != 0 { + x := rcv._tab.Vector(o) + x += flatbuffers.UOffsetT(j) * 16 + obj.Init(rcv._tab.Bytes, x) + return true + } + return false +} + +func (rcv *RecordBatch) NodesLength() int { + o := flatbuffers.UOffsetT(rcv._tab.Offset(6)) + if o != 0 { + return rcv._tab.VectorLen(o) + } + return 0 +} + +/// Nodes correspond to the pre-ordered flattened logical schema +/// Buffers correspond to the pre-ordered flattened buffer tree +/// +/// The number of buffers appended to this list depends on the schema. For +/// example, most primitive arrays will have 2 buffers, 1 for the validity +/// bitmap and 1 for the values. For struct arrays, there will only be a +/// single buffer for the validity (nulls) bitmap +func (rcv *RecordBatch) Buffers(obj *Buffer, j int) bool { + o := flatbuffers.UOffsetT(rcv._tab.Offset(8)) + if o != 0 { + x := rcv._tab.Vector(o) + x += flatbuffers.UOffsetT(j) * 16 + obj.Init(rcv._tab.Bytes, x) + return true + } + return false +} + +func (rcv *RecordBatch) BuffersLength() int { + o := flatbuffers.UOffsetT(rcv._tab.Offset(8)) + if o != 0 { + return rcv._tab.VectorLen(o) + } + return 0 +} + +/// Buffers correspond to the pre-ordered flattened buffer tree +/// +/// The number of buffers appended to this list depends on the schema. For +/// example, most primitive arrays will have 2 buffers, 1 for the validity +/// bitmap and 1 for the values. For struct arrays, there will only be a +/// single buffer for the validity (nulls) bitmap +/// Optional compression of the message body +func (rcv *RecordBatch) Compression(obj *BodyCompression) *BodyCompression { + o := flatbuffers.UOffsetT(rcv._tab.Offset(10)) + if o != 0 { + x := rcv._tab.Indirect(o + rcv._tab.Pos) + if obj == nil { + obj = new(BodyCompression) + } + obj.Init(rcv._tab.Bytes, x) + return obj + } + return nil +} + +/// Optional compression of the message body +/// Some types such as Utf8View are represented using a variable number of buffers. +/// For each such Field in the pre-ordered flattened logical schema, there will be +/// an entry in variadicBufferCounts to indicate the number of number of variadic +/// buffers which belong to that Field in the current RecordBatch. +/// +/// For example, the schema +/// col1: Struct +/// col2: Utf8View +/// contains two Fields with variadic buffers so variadicBufferCounts will have +/// two entries, the first counting the variadic buffers of `col1.beta` and the +/// second counting `col2`'s. +/// +/// This field may be omitted if and only if the schema contains no Fields with +/// a variable number of buffers, such as BinaryView and Utf8View. +func (rcv *RecordBatch) VariadicBufferCounts(j int) int64 { + o := flatbuffers.UOffsetT(rcv._tab.Offset(12)) + if o != 0 { + a := rcv._tab.Vector(o) + return rcv._tab.GetInt64(a + flatbuffers.UOffsetT(j*8)) + } + return 0 +} + +func (rcv *RecordBatch) VariadicBufferCountsLength() int { + o := flatbuffers.UOffsetT(rcv._tab.Offset(12)) + if o != 0 { + return rcv._tab.VectorLen(o) + } + return 0 +} + +/// Some types such as Utf8View are represented using a variable number of buffers. +/// For each such Field in the pre-ordered flattened logical schema, there will be +/// an entry in variadicBufferCounts to indicate the number of number of variadic +/// buffers which belong to that Field in the current RecordBatch. +/// +/// For example, the schema +/// col1: Struct +/// col2: Utf8View +/// contains two Fields with variadic buffers so variadicBufferCounts will have +/// two entries, the first counting the variadic buffers of `col1.beta` and the +/// second counting `col2`'s. +/// +/// This field may be omitted if and only if the schema contains no Fields with +/// a variable number of buffers, such as BinaryView and Utf8View. +func (rcv *RecordBatch) MutateVariadicBufferCounts(j int, n int64) bool { + o := flatbuffers.UOffsetT(rcv._tab.Offset(12)) + if o != 0 { + a := rcv._tab.Vector(o) + return rcv._tab.MutateInt64(a+flatbuffers.UOffsetT(j*8), n) + } + return false +} + +func RecordBatchStart(builder *flatbuffers.Builder) { + builder.StartObject(5) +} +func RecordBatchAddLength(builder *flatbuffers.Builder, length int64) { + builder.PrependInt64Slot(0, length, 0) +} +func RecordBatchAddNodes(builder *flatbuffers.Builder, nodes flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(1, flatbuffers.UOffsetT(nodes), 0) +} +func RecordBatchStartNodesVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT { + return builder.StartVector(16, numElems, 8) +} +func RecordBatchAddBuffers(builder *flatbuffers.Builder, buffers flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(2, flatbuffers.UOffsetT(buffers), 0) +} +func RecordBatchStartBuffersVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT { + return builder.StartVector(16, numElems, 8) +} +func RecordBatchAddCompression(builder *flatbuffers.Builder, compression flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(3, flatbuffers.UOffsetT(compression), 0) +} +func RecordBatchAddVariadicBufferCounts(builder *flatbuffers.Builder, variadicBufferCounts flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(4, flatbuffers.UOffsetT(variadicBufferCounts), 0) +} +func RecordBatchStartVariadicBufferCountsVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT { + return builder.StartVector(8, numElems, 8) +} +func RecordBatchEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/RunEndEncoded.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/RunEndEncoded.go new file mode 100644 index 000000000..fa414c1bf --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/RunEndEncoded.go @@ -0,0 +1,55 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +/// Contains two child arrays, run_ends and values. +/// The run_ends child array must be a 16/32/64-bit integer array +/// which encodes the indices at which the run with the value in +/// each corresponding index in the values child array ends. +/// Like list/struct types, the value array can be of any type. +type RunEndEncoded struct { + _tab flatbuffers.Table +} + +func GetRootAsRunEndEncoded(buf []byte, offset flatbuffers.UOffsetT) *RunEndEncoded { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &RunEndEncoded{} + x.Init(buf, n+offset) + return x +} + +func (rcv *RunEndEncoded) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *RunEndEncoded) Table() flatbuffers.Table { + return rcv._tab +} + +func RunEndEncodedStart(builder *flatbuffers.Builder) { + builder.StartObject(0) +} +func RunEndEncodedEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/RunLengthEncoded.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/RunLengthEncoded.go new file mode 100644 index 000000000..8822c0660 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/RunLengthEncoded.go @@ -0,0 +1,50 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +type RunLengthEncoded struct { + _tab flatbuffers.Table +} + +func GetRootAsRunLengthEncoded(buf []byte, offset flatbuffers.UOffsetT) *RunLengthEncoded { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &RunLengthEncoded{} + x.Init(buf, n+offset) + return x +} + +func (rcv *RunLengthEncoded) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *RunLengthEncoded) Table() flatbuffers.Table { + return rcv._tab +} + +func RunLengthEncodedStart(builder *flatbuffers.Builder) { + builder.StartObject(0) +} +func RunLengthEncodedEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Schema.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Schema.go new file mode 100644 index 000000000..4ee5ecc9e --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Schema.go @@ -0,0 +1,159 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +/// ---------------------------------------------------------------------- +/// A Schema describes the columns in a row batch +type Schema struct { + _tab flatbuffers.Table +} + +func GetRootAsSchema(buf []byte, offset flatbuffers.UOffsetT) *Schema { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &Schema{} + x.Init(buf, n+offset) + return x +} + +func (rcv *Schema) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *Schema) Table() flatbuffers.Table { + return rcv._tab +} + +/// endianness of the buffer +/// it is Little Endian by default +/// if endianness doesn't match the underlying system then the vectors need to be converted +func (rcv *Schema) Endianness() Endianness { + o := flatbuffers.UOffsetT(rcv._tab.Offset(4)) + if o != 0 { + return Endianness(rcv._tab.GetInt16(o + rcv._tab.Pos)) + } + return 0 +} + +/// endianness of the buffer +/// it is Little Endian by default +/// if endianness doesn't match the underlying system then the vectors need to be converted +func (rcv *Schema) MutateEndianness(n Endianness) bool { + return rcv._tab.MutateInt16Slot(4, int16(n)) +} + +func (rcv *Schema) Fields(obj *Field, j int) bool { + o := flatbuffers.UOffsetT(rcv._tab.Offset(6)) + if o != 0 { + x := rcv._tab.Vector(o) + x += flatbuffers.UOffsetT(j) * 4 + x = rcv._tab.Indirect(x) + obj.Init(rcv._tab.Bytes, x) + return true + } + return false +} + +func (rcv *Schema) FieldsLength() int { + o := flatbuffers.UOffsetT(rcv._tab.Offset(6)) + if o != 0 { + return rcv._tab.VectorLen(o) + } + return 0 +} + +func (rcv *Schema) CustomMetadata(obj *KeyValue, j int) bool { + o := flatbuffers.UOffsetT(rcv._tab.Offset(8)) + if o != 0 { + x := rcv._tab.Vector(o) + x += flatbuffers.UOffsetT(j) * 4 + x = rcv._tab.Indirect(x) + obj.Init(rcv._tab.Bytes, x) + return true + } + return false +} + +func (rcv *Schema) CustomMetadataLength() int { + o := flatbuffers.UOffsetT(rcv._tab.Offset(8)) + if o != 0 { + return rcv._tab.VectorLen(o) + } + return 0 +} + +/// Features used in the stream/file. +func (rcv *Schema) Features(j int) Feature { + o := flatbuffers.UOffsetT(rcv._tab.Offset(10)) + if o != 0 { + a := rcv._tab.Vector(o) + return Feature(rcv._tab.GetInt64(a + flatbuffers.UOffsetT(j*8))) + } + return 0 +} + +func (rcv *Schema) FeaturesLength() int { + o := flatbuffers.UOffsetT(rcv._tab.Offset(10)) + if o != 0 { + return rcv._tab.VectorLen(o) + } + return 0 +} + +/// Features used in the stream/file. +func (rcv *Schema) MutateFeatures(j int, n Feature) bool { + o := flatbuffers.UOffsetT(rcv._tab.Offset(10)) + if o != 0 { + a := rcv._tab.Vector(o) + return rcv._tab.MutateInt64(a+flatbuffers.UOffsetT(j*8), int64(n)) + } + return false +} + +func SchemaStart(builder *flatbuffers.Builder) { + builder.StartObject(4) +} +func SchemaAddEndianness(builder *flatbuffers.Builder, endianness Endianness) { + builder.PrependInt16Slot(0, int16(endianness), 0) +} +func SchemaAddFields(builder *flatbuffers.Builder, fields flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(1, flatbuffers.UOffsetT(fields), 0) +} +func SchemaStartFieldsVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT { + return builder.StartVector(4, numElems, 4) +} +func SchemaAddCustomMetadata(builder *flatbuffers.Builder, customMetadata flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(2, flatbuffers.UOffsetT(customMetadata), 0) +} +func SchemaStartCustomMetadataVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT { + return builder.StartVector(4, numElems, 4) +} +func SchemaAddFeatures(builder *flatbuffers.Builder, features flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(3, flatbuffers.UOffsetT(features), 0) +} +func SchemaStartFeaturesVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT { + return builder.StartVector(8, numElems, 8) +} +func SchemaEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/SparseMatrixCompressedAxis.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/SparseMatrixCompressedAxis.go new file mode 100644 index 000000000..2d86fdef7 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/SparseMatrixCompressedAxis.go @@ -0,0 +1,45 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import "strconv" + +type SparseMatrixCompressedAxis int16 + +const ( + SparseMatrixCompressedAxisRow SparseMatrixCompressedAxis = 0 + SparseMatrixCompressedAxisColumn SparseMatrixCompressedAxis = 1 +) + +var EnumNamesSparseMatrixCompressedAxis = map[SparseMatrixCompressedAxis]string{ + SparseMatrixCompressedAxisRow: "Row", + SparseMatrixCompressedAxisColumn: "Column", +} + +var EnumValuesSparseMatrixCompressedAxis = map[string]SparseMatrixCompressedAxis{ + "Row": SparseMatrixCompressedAxisRow, + "Column": SparseMatrixCompressedAxisColumn, +} + +func (v SparseMatrixCompressedAxis) String() string { + if s, ok := EnumNamesSparseMatrixCompressedAxis[v]; ok { + return s + } + return "SparseMatrixCompressedAxis(" + strconv.FormatInt(int64(v), 10) + ")" +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/SparseMatrixIndexCSR.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/SparseMatrixIndexCSR.go new file mode 100644 index 000000000..de8217650 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/SparseMatrixIndexCSR.go @@ -0,0 +1,181 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +/// Compressed Sparse Row format, that is matrix-specific. +type SparseMatrixIndexCSR struct { + _tab flatbuffers.Table +} + +func GetRootAsSparseMatrixIndexCSR(buf []byte, offset flatbuffers.UOffsetT) *SparseMatrixIndexCSR { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &SparseMatrixIndexCSR{} + x.Init(buf, n+offset) + return x +} + +func (rcv *SparseMatrixIndexCSR) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *SparseMatrixIndexCSR) Table() flatbuffers.Table { + return rcv._tab +} + +/// The type of values in indptrBuffer +func (rcv *SparseMatrixIndexCSR) IndptrType(obj *Int) *Int { + o := flatbuffers.UOffsetT(rcv._tab.Offset(4)) + if o != 0 { + x := rcv._tab.Indirect(o + rcv._tab.Pos) + if obj == nil { + obj = new(Int) + } + obj.Init(rcv._tab.Bytes, x) + return obj + } + return nil +} + +/// The type of values in indptrBuffer +/// indptrBuffer stores the location and size of indptr array that +/// represents the range of the rows. +/// The i-th row spans from indptr[i] to indptr[i+1] in the data. +/// The length of this array is 1 + (the number of rows), and the type +/// of index value is long. +/// +/// For example, let X be the following 6x4 matrix: +/// +/// X := [[0, 1, 2, 0], +/// [0, 0, 3, 0], +/// [0, 4, 0, 5], +/// [0, 0, 0, 0], +/// [6, 0, 7, 8], +/// [0, 9, 0, 0]]. +/// +/// The array of non-zero values in X is: +/// +/// values(X) = [1, 2, 3, 4, 5, 6, 7, 8, 9]. +/// +/// And the indptr of X is: +/// +/// indptr(X) = [0, 2, 3, 5, 5, 8, 10]. +func (rcv *SparseMatrixIndexCSR) IndptrBuffer(obj *Buffer) *Buffer { + o := flatbuffers.UOffsetT(rcv._tab.Offset(6)) + if o != 0 { + x := o + rcv._tab.Pos + if obj == nil { + obj = new(Buffer) + } + obj.Init(rcv._tab.Bytes, x) + return obj + } + return nil +} + +/// indptrBuffer stores the location and size of indptr array that +/// represents the range of the rows. +/// The i-th row spans from indptr[i] to indptr[i+1] in the data. +/// The length of this array is 1 + (the number of rows), and the type +/// of index value is long. +/// +/// For example, let X be the following 6x4 matrix: +/// +/// X := [[0, 1, 2, 0], +/// [0, 0, 3, 0], +/// [0, 4, 0, 5], +/// [0, 0, 0, 0], +/// [6, 0, 7, 8], +/// [0, 9, 0, 0]]. +/// +/// The array of non-zero values in X is: +/// +/// values(X) = [1, 2, 3, 4, 5, 6, 7, 8, 9]. +/// +/// And the indptr of X is: +/// +/// indptr(X) = [0, 2, 3, 5, 5, 8, 10]. +/// The type of values in indicesBuffer +func (rcv *SparseMatrixIndexCSR) IndicesType(obj *Int) *Int { + o := flatbuffers.UOffsetT(rcv._tab.Offset(8)) + if o != 0 { + x := rcv._tab.Indirect(o + rcv._tab.Pos) + if obj == nil { + obj = new(Int) + } + obj.Init(rcv._tab.Bytes, x) + return obj + } + return nil +} + +/// The type of values in indicesBuffer +/// indicesBuffer stores the location and size of the array that +/// contains the column indices of the corresponding non-zero values. +/// The type of index value is long. +/// +/// For example, the indices of the above X is: +/// +/// indices(X) = [1, 2, 2, 1, 3, 0, 2, 3, 1]. +/// +/// Note that the indices are sorted in lexicographical order for each row. +func (rcv *SparseMatrixIndexCSR) IndicesBuffer(obj *Buffer) *Buffer { + o := flatbuffers.UOffsetT(rcv._tab.Offset(10)) + if o != 0 { + x := o + rcv._tab.Pos + if obj == nil { + obj = new(Buffer) + } + obj.Init(rcv._tab.Bytes, x) + return obj + } + return nil +} + +/// indicesBuffer stores the location and size of the array that +/// contains the column indices of the corresponding non-zero values. +/// The type of index value is long. +/// +/// For example, the indices of the above X is: +/// +/// indices(X) = [1, 2, 2, 1, 3, 0, 2, 3, 1]. +/// +/// Note that the indices are sorted in lexicographical order for each row. +func SparseMatrixIndexCSRStart(builder *flatbuffers.Builder) { + builder.StartObject(4) +} +func SparseMatrixIndexCSRAddIndptrType(builder *flatbuffers.Builder, indptrType flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(indptrType), 0) +} +func SparseMatrixIndexCSRAddIndptrBuffer(builder *flatbuffers.Builder, indptrBuffer flatbuffers.UOffsetT) { + builder.PrependStructSlot(1, flatbuffers.UOffsetT(indptrBuffer), 0) +} +func SparseMatrixIndexCSRAddIndicesType(builder *flatbuffers.Builder, indicesType flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(2, flatbuffers.UOffsetT(indicesType), 0) +} +func SparseMatrixIndexCSRAddIndicesBuffer(builder *flatbuffers.Builder, indicesBuffer flatbuffers.UOffsetT) { + builder.PrependStructSlot(3, flatbuffers.UOffsetT(indicesBuffer), 0) +} +func SparseMatrixIndexCSREnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/SparseMatrixIndexCSX.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/SparseMatrixIndexCSX.go new file mode 100644 index 000000000..c28cc5d08 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/SparseMatrixIndexCSX.go @@ -0,0 +1,200 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +/// Compressed Sparse format, that is matrix-specific. +type SparseMatrixIndexCSX struct { + _tab flatbuffers.Table +} + +func GetRootAsSparseMatrixIndexCSX(buf []byte, offset flatbuffers.UOffsetT) *SparseMatrixIndexCSX { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &SparseMatrixIndexCSX{} + x.Init(buf, n+offset) + return x +} + +func (rcv *SparseMatrixIndexCSX) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *SparseMatrixIndexCSX) Table() flatbuffers.Table { + return rcv._tab +} + +/// Which axis, row or column, is compressed +func (rcv *SparseMatrixIndexCSX) CompressedAxis() SparseMatrixCompressedAxis { + o := flatbuffers.UOffsetT(rcv._tab.Offset(4)) + if o != 0 { + return SparseMatrixCompressedAxis(rcv._tab.GetInt16(o + rcv._tab.Pos)) + } + return 0 +} + +/// Which axis, row or column, is compressed +func (rcv *SparseMatrixIndexCSX) MutateCompressedAxis(n SparseMatrixCompressedAxis) bool { + return rcv._tab.MutateInt16Slot(4, int16(n)) +} + +/// The type of values in indptrBuffer +func (rcv *SparseMatrixIndexCSX) IndptrType(obj *Int) *Int { + o := flatbuffers.UOffsetT(rcv._tab.Offset(6)) + if o != 0 { + x := rcv._tab.Indirect(o + rcv._tab.Pos) + if obj == nil { + obj = new(Int) + } + obj.Init(rcv._tab.Bytes, x) + return obj + } + return nil +} + +/// The type of values in indptrBuffer +/// indptrBuffer stores the location and size of indptr array that +/// represents the range of the rows. +/// The i-th row spans from `indptr[i]` to `indptr[i+1]` in the data. +/// The length of this array is 1 + (the number of rows), and the type +/// of index value is long. +/// +/// For example, let X be the following 6x4 matrix: +/// ```text +/// X := [[0, 1, 2, 0], +/// [0, 0, 3, 0], +/// [0, 4, 0, 5], +/// [0, 0, 0, 0], +/// [6, 0, 7, 8], +/// [0, 9, 0, 0]]. +/// ``` +/// The array of non-zero values in X is: +/// ```text +/// values(X) = [1, 2, 3, 4, 5, 6, 7, 8, 9]. +/// ``` +/// And the indptr of X is: +/// ```text +/// indptr(X) = [0, 2, 3, 5, 5, 8, 10]. +/// ``` +func (rcv *SparseMatrixIndexCSX) IndptrBuffer(obj *Buffer) *Buffer { + o := flatbuffers.UOffsetT(rcv._tab.Offset(8)) + if o != 0 { + x := o + rcv._tab.Pos + if obj == nil { + obj = new(Buffer) + } + obj.Init(rcv._tab.Bytes, x) + return obj + } + return nil +} + +/// indptrBuffer stores the location and size of indptr array that +/// represents the range of the rows. +/// The i-th row spans from `indptr[i]` to `indptr[i+1]` in the data. +/// The length of this array is 1 + (the number of rows), and the type +/// of index value is long. +/// +/// For example, let X be the following 6x4 matrix: +/// ```text +/// X := [[0, 1, 2, 0], +/// [0, 0, 3, 0], +/// [0, 4, 0, 5], +/// [0, 0, 0, 0], +/// [6, 0, 7, 8], +/// [0, 9, 0, 0]]. +/// ``` +/// The array of non-zero values in X is: +/// ```text +/// values(X) = [1, 2, 3, 4, 5, 6, 7, 8, 9]. +/// ``` +/// And the indptr of X is: +/// ```text +/// indptr(X) = [0, 2, 3, 5, 5, 8, 10]. +/// ``` +/// The type of values in indicesBuffer +func (rcv *SparseMatrixIndexCSX) IndicesType(obj *Int) *Int { + o := flatbuffers.UOffsetT(rcv._tab.Offset(10)) + if o != 0 { + x := rcv._tab.Indirect(o + rcv._tab.Pos) + if obj == nil { + obj = new(Int) + } + obj.Init(rcv._tab.Bytes, x) + return obj + } + return nil +} + +/// The type of values in indicesBuffer +/// indicesBuffer stores the location and size of the array that +/// contains the column indices of the corresponding non-zero values. +/// The type of index value is long. +/// +/// For example, the indices of the above X is: +/// ```text +/// indices(X) = [1, 2, 2, 1, 3, 0, 2, 3, 1]. +/// ``` +/// Note that the indices are sorted in lexicographical order for each row. +func (rcv *SparseMatrixIndexCSX) IndicesBuffer(obj *Buffer) *Buffer { + o := flatbuffers.UOffsetT(rcv._tab.Offset(12)) + if o != 0 { + x := o + rcv._tab.Pos + if obj == nil { + obj = new(Buffer) + } + obj.Init(rcv._tab.Bytes, x) + return obj + } + return nil +} + +/// indicesBuffer stores the location and size of the array that +/// contains the column indices of the corresponding non-zero values. +/// The type of index value is long. +/// +/// For example, the indices of the above X is: +/// ```text +/// indices(X) = [1, 2, 2, 1, 3, 0, 2, 3, 1]. +/// ``` +/// Note that the indices are sorted in lexicographical order for each row. +func SparseMatrixIndexCSXStart(builder *flatbuffers.Builder) { + builder.StartObject(5) +} +func SparseMatrixIndexCSXAddCompressedAxis(builder *flatbuffers.Builder, compressedAxis SparseMatrixCompressedAxis) { + builder.PrependInt16Slot(0, int16(compressedAxis), 0) +} +func SparseMatrixIndexCSXAddIndptrType(builder *flatbuffers.Builder, indptrType flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(1, flatbuffers.UOffsetT(indptrType), 0) +} +func SparseMatrixIndexCSXAddIndptrBuffer(builder *flatbuffers.Builder, indptrBuffer flatbuffers.UOffsetT) { + builder.PrependStructSlot(2, flatbuffers.UOffsetT(indptrBuffer), 0) +} +func SparseMatrixIndexCSXAddIndicesType(builder *flatbuffers.Builder, indicesType flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(3, flatbuffers.UOffsetT(indicesType), 0) +} +func SparseMatrixIndexCSXAddIndicesBuffer(builder *flatbuffers.Builder, indicesBuffer flatbuffers.UOffsetT) { + builder.PrependStructSlot(4, flatbuffers.UOffsetT(indicesBuffer), 0) +} +func SparseMatrixIndexCSXEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/SparseTensor.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/SparseTensor.go new file mode 100644 index 000000000..6f3f55797 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/SparseTensor.go @@ -0,0 +1,175 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +type SparseTensor struct { + _tab flatbuffers.Table +} + +func GetRootAsSparseTensor(buf []byte, offset flatbuffers.UOffsetT) *SparseTensor { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &SparseTensor{} + x.Init(buf, n+offset) + return x +} + +func (rcv *SparseTensor) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *SparseTensor) Table() flatbuffers.Table { + return rcv._tab +} + +func (rcv *SparseTensor) TypeType() Type { + o := flatbuffers.UOffsetT(rcv._tab.Offset(4)) + if o != 0 { + return Type(rcv._tab.GetByte(o + rcv._tab.Pos)) + } + return 0 +} + +func (rcv *SparseTensor) MutateTypeType(n Type) bool { + return rcv._tab.MutateByteSlot(4, byte(n)) +} + +/// The type of data contained in a value cell. +/// Currently only fixed-width value types are supported, +/// no strings or nested types. +func (rcv *SparseTensor) Type(obj *flatbuffers.Table) bool { + o := flatbuffers.UOffsetT(rcv._tab.Offset(6)) + if o != 0 { + rcv._tab.Union(obj, o) + return true + } + return false +} + +/// The type of data contained in a value cell. +/// Currently only fixed-width value types are supported, +/// no strings or nested types. +/// The dimensions of the tensor, optionally named. +func (rcv *SparseTensor) Shape(obj *TensorDim, j int) bool { + o := flatbuffers.UOffsetT(rcv._tab.Offset(8)) + if o != 0 { + x := rcv._tab.Vector(o) + x += flatbuffers.UOffsetT(j) * 4 + x = rcv._tab.Indirect(x) + obj.Init(rcv._tab.Bytes, x) + return true + } + return false +} + +func (rcv *SparseTensor) ShapeLength() int { + o := flatbuffers.UOffsetT(rcv._tab.Offset(8)) + if o != 0 { + return rcv._tab.VectorLen(o) + } + return 0 +} + +/// The dimensions of the tensor, optionally named. +/// The number of non-zero values in a sparse tensor. +func (rcv *SparseTensor) NonZeroLength() int64 { + o := flatbuffers.UOffsetT(rcv._tab.Offset(10)) + if o != 0 { + return rcv._tab.GetInt64(o + rcv._tab.Pos) + } + return 0 +} + +/// The number of non-zero values in a sparse tensor. +func (rcv *SparseTensor) MutateNonZeroLength(n int64) bool { + return rcv._tab.MutateInt64Slot(10, n) +} + +func (rcv *SparseTensor) SparseIndexType() SparseTensorIndex { + o := flatbuffers.UOffsetT(rcv._tab.Offset(12)) + if o != 0 { + return SparseTensorIndex(rcv._tab.GetByte(o + rcv._tab.Pos)) + } + return 0 +} + +func (rcv *SparseTensor) MutateSparseIndexType(n SparseTensorIndex) bool { + return rcv._tab.MutateByteSlot(12, byte(n)) +} + +/// Sparse tensor index +func (rcv *SparseTensor) SparseIndex(obj *flatbuffers.Table) bool { + o := flatbuffers.UOffsetT(rcv._tab.Offset(14)) + if o != 0 { + rcv._tab.Union(obj, o) + return true + } + return false +} + +/// Sparse tensor index +/// The location and size of the tensor's data +func (rcv *SparseTensor) Data(obj *Buffer) *Buffer { + o := flatbuffers.UOffsetT(rcv._tab.Offset(16)) + if o != 0 { + x := o + rcv._tab.Pos + if obj == nil { + obj = new(Buffer) + } + obj.Init(rcv._tab.Bytes, x) + return obj + } + return nil +} + +/// The location and size of the tensor's data +func SparseTensorStart(builder *flatbuffers.Builder) { + builder.StartObject(7) +} +func SparseTensorAddTypeType(builder *flatbuffers.Builder, typeType Type) { + builder.PrependByteSlot(0, byte(typeType), 0) +} +func SparseTensorAddType(builder *flatbuffers.Builder, type_ flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(1, flatbuffers.UOffsetT(type_), 0) +} +func SparseTensorAddShape(builder *flatbuffers.Builder, shape flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(2, flatbuffers.UOffsetT(shape), 0) +} +func SparseTensorStartShapeVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT { + return builder.StartVector(4, numElems, 4) +} +func SparseTensorAddNonZeroLength(builder *flatbuffers.Builder, nonZeroLength int64) { + builder.PrependInt64Slot(3, nonZeroLength, 0) +} +func SparseTensorAddSparseIndexType(builder *flatbuffers.Builder, sparseIndexType SparseTensorIndex) { + builder.PrependByteSlot(4, byte(sparseIndexType), 0) +} +func SparseTensorAddSparseIndex(builder *flatbuffers.Builder, sparseIndex flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(5, flatbuffers.UOffsetT(sparseIndex), 0) +} +func SparseTensorAddData(builder *flatbuffers.Builder, data flatbuffers.UOffsetT) { + builder.PrependStructSlot(6, flatbuffers.UOffsetT(data), 0) +} +func SparseTensorEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/SparseTensorIndex.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/SparseTensorIndex.go new file mode 100644 index 000000000..42aa818b0 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/SparseTensorIndex.go @@ -0,0 +1,51 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import "strconv" + +type SparseTensorIndex byte + +const ( + SparseTensorIndexNONE SparseTensorIndex = 0 + SparseTensorIndexSparseTensorIndexCOO SparseTensorIndex = 1 + SparseTensorIndexSparseMatrixIndexCSX SparseTensorIndex = 2 + SparseTensorIndexSparseTensorIndexCSF SparseTensorIndex = 3 +) + +var EnumNamesSparseTensorIndex = map[SparseTensorIndex]string{ + SparseTensorIndexNONE: "NONE", + SparseTensorIndexSparseTensorIndexCOO: "SparseTensorIndexCOO", + SparseTensorIndexSparseMatrixIndexCSX: "SparseMatrixIndexCSX", + SparseTensorIndexSparseTensorIndexCSF: "SparseTensorIndexCSF", +} + +var EnumValuesSparseTensorIndex = map[string]SparseTensorIndex{ + "NONE": SparseTensorIndexNONE, + "SparseTensorIndexCOO": SparseTensorIndexSparseTensorIndexCOO, + "SparseMatrixIndexCSX": SparseTensorIndexSparseMatrixIndexCSX, + "SparseTensorIndexCSF": SparseTensorIndexSparseTensorIndexCSF, +} + +func (v SparseTensorIndex) String() string { + if s, ok := EnumNamesSparseTensorIndex[v]; ok { + return s + } + return "SparseTensorIndex(" + strconv.FormatInt(int64(v), 10) + ")" +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/SparseTensorIndexCOO.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/SparseTensorIndexCOO.go new file mode 100644 index 000000000..f8eee99fa --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/SparseTensorIndexCOO.go @@ -0,0 +1,179 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +/// ---------------------------------------------------------------------- +/// EXPERIMENTAL: Data structures for sparse tensors +/// Coordinate (COO) format of sparse tensor index. +/// +/// COO's index list are represented as a NxM matrix, +/// where N is the number of non-zero values, +/// and M is the number of dimensions of a sparse tensor. +/// +/// indicesBuffer stores the location and size of the data of this indices +/// matrix. The value type and the stride of the indices matrix is +/// specified in indicesType and indicesStrides fields. +/// +/// For example, let X be a 2x3x4x5 tensor, and it has the following +/// 6 non-zero values: +/// ```text +/// X[0, 1, 2, 0] := 1 +/// X[1, 1, 2, 3] := 2 +/// X[0, 2, 1, 0] := 3 +/// X[0, 1, 3, 0] := 4 +/// X[0, 1, 2, 1] := 5 +/// X[1, 2, 0, 4] := 6 +/// ``` +/// In COO format, the index matrix of X is the following 4x6 matrix: +/// ```text +/// [[0, 0, 0, 0, 1, 1], +/// [1, 1, 1, 2, 1, 2], +/// [2, 2, 3, 1, 2, 0], +/// [0, 1, 0, 0, 3, 4]] +/// ``` +/// When isCanonical is true, the indices is sorted in lexicographical order +/// (row-major order), and it does not have duplicated entries. Otherwise, +/// the indices may not be sorted, or may have duplicated entries. +type SparseTensorIndexCOO struct { + _tab flatbuffers.Table +} + +func GetRootAsSparseTensorIndexCOO(buf []byte, offset flatbuffers.UOffsetT) *SparseTensorIndexCOO { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &SparseTensorIndexCOO{} + x.Init(buf, n+offset) + return x +} + +func (rcv *SparseTensorIndexCOO) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *SparseTensorIndexCOO) Table() flatbuffers.Table { + return rcv._tab +} + +/// The type of values in indicesBuffer +func (rcv *SparseTensorIndexCOO) IndicesType(obj *Int) *Int { + o := flatbuffers.UOffsetT(rcv._tab.Offset(4)) + if o != 0 { + x := rcv._tab.Indirect(o + rcv._tab.Pos) + if obj == nil { + obj = new(Int) + } + obj.Init(rcv._tab.Bytes, x) + return obj + } + return nil +} + +/// The type of values in indicesBuffer +/// Non-negative byte offsets to advance one value cell along each dimension +/// If omitted, default to row-major order (C-like). +func (rcv *SparseTensorIndexCOO) IndicesStrides(j int) int64 { + o := flatbuffers.UOffsetT(rcv._tab.Offset(6)) + if o != 0 { + a := rcv._tab.Vector(o) + return rcv._tab.GetInt64(a + flatbuffers.UOffsetT(j*8)) + } + return 0 +} + +func (rcv *SparseTensorIndexCOO) IndicesStridesLength() int { + o := flatbuffers.UOffsetT(rcv._tab.Offset(6)) + if o != 0 { + return rcv._tab.VectorLen(o) + } + return 0 +} + +/// Non-negative byte offsets to advance one value cell along each dimension +/// If omitted, default to row-major order (C-like). +func (rcv *SparseTensorIndexCOO) MutateIndicesStrides(j int, n int64) bool { + o := flatbuffers.UOffsetT(rcv._tab.Offset(6)) + if o != 0 { + a := rcv._tab.Vector(o) + return rcv._tab.MutateInt64(a+flatbuffers.UOffsetT(j*8), n) + } + return false +} + +/// The location and size of the indices matrix's data +func (rcv *SparseTensorIndexCOO) IndicesBuffer(obj *Buffer) *Buffer { + o := flatbuffers.UOffsetT(rcv._tab.Offset(8)) + if o != 0 { + x := o + rcv._tab.Pos + if obj == nil { + obj = new(Buffer) + } + obj.Init(rcv._tab.Bytes, x) + return obj + } + return nil +} + +/// The location and size of the indices matrix's data +/// This flag is true if and only if the indices matrix is sorted in +/// row-major order, and does not have duplicated entries. +/// This sort order is the same as of Tensorflow's SparseTensor, +/// but it is inverse order of SciPy's canonical coo_matrix +/// (SciPy employs column-major order for its coo_matrix). +func (rcv *SparseTensorIndexCOO) IsCanonical() bool { + o := flatbuffers.UOffsetT(rcv._tab.Offset(10)) + if o != 0 { + return rcv._tab.GetBool(o + rcv._tab.Pos) + } + return false +} + +/// This flag is true if and only if the indices matrix is sorted in +/// row-major order, and does not have duplicated entries. +/// This sort order is the same as of Tensorflow's SparseTensor, +/// but it is inverse order of SciPy's canonical coo_matrix +/// (SciPy employs column-major order for its coo_matrix). +func (rcv *SparseTensorIndexCOO) MutateIsCanonical(n bool) bool { + return rcv._tab.MutateBoolSlot(10, n) +} + +func SparseTensorIndexCOOStart(builder *flatbuffers.Builder) { + builder.StartObject(4) +} +func SparseTensorIndexCOOAddIndicesType(builder *flatbuffers.Builder, indicesType flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(indicesType), 0) +} +func SparseTensorIndexCOOAddIndicesStrides(builder *flatbuffers.Builder, indicesStrides flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(1, flatbuffers.UOffsetT(indicesStrides), 0) +} +func SparseTensorIndexCOOStartIndicesStridesVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT { + return builder.StartVector(8, numElems, 8) +} +func SparseTensorIndexCOOAddIndicesBuffer(builder *flatbuffers.Builder, indicesBuffer flatbuffers.UOffsetT) { + builder.PrependStructSlot(2, flatbuffers.UOffsetT(indicesBuffer), 0) +} +func SparseTensorIndexCOOAddIsCanonical(builder *flatbuffers.Builder, isCanonical bool) { + builder.PrependBoolSlot(3, isCanonical, false) +} +func SparseTensorIndexCOOEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/SparseTensorIndexCSF.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/SparseTensorIndexCSF.go new file mode 100644 index 000000000..a824c84eb --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/SparseTensorIndexCSF.go @@ -0,0 +1,291 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +/// Compressed Sparse Fiber (CSF) sparse tensor index. +type SparseTensorIndexCSF struct { + _tab flatbuffers.Table +} + +func GetRootAsSparseTensorIndexCSF(buf []byte, offset flatbuffers.UOffsetT) *SparseTensorIndexCSF { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &SparseTensorIndexCSF{} + x.Init(buf, n+offset) + return x +} + +func (rcv *SparseTensorIndexCSF) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *SparseTensorIndexCSF) Table() flatbuffers.Table { + return rcv._tab +} + +/// CSF is a generalization of compressed sparse row (CSR) index. +/// See [smith2017knl](http://shaden.io/pub-files/smith2017knl.pdf) +/// +/// CSF index recursively compresses each dimension of a tensor into a set +/// of prefix trees. Each path from a root to leaf forms one tensor +/// non-zero index. CSF is implemented with two arrays of buffers and one +/// arrays of integers. +/// +/// For example, let X be a 2x3x4x5 tensor and let it have the following +/// 8 non-zero values: +/// ```text +/// X[0, 0, 0, 1] := 1 +/// X[0, 0, 0, 2] := 2 +/// X[0, 1, 0, 0] := 3 +/// X[0, 1, 0, 2] := 4 +/// X[0, 1, 1, 0] := 5 +/// X[1, 1, 1, 0] := 6 +/// X[1, 1, 1, 1] := 7 +/// X[1, 1, 1, 2] := 8 +/// ``` +/// As a prefix tree this would be represented as: +/// ```text +/// 0 1 +/// / \ | +/// 0 1 1 +/// / / \ | +/// 0 0 1 1 +/// /| /| | /| | +/// 1 2 0 2 0 0 1 2 +/// ``` +/// The type of values in indptrBuffers +func (rcv *SparseTensorIndexCSF) IndptrType(obj *Int) *Int { + o := flatbuffers.UOffsetT(rcv._tab.Offset(4)) + if o != 0 { + x := rcv._tab.Indirect(o + rcv._tab.Pos) + if obj == nil { + obj = new(Int) + } + obj.Init(rcv._tab.Bytes, x) + return obj + } + return nil +} + +/// CSF is a generalization of compressed sparse row (CSR) index. +/// See [smith2017knl](http://shaden.io/pub-files/smith2017knl.pdf) +/// +/// CSF index recursively compresses each dimension of a tensor into a set +/// of prefix trees. Each path from a root to leaf forms one tensor +/// non-zero index. CSF is implemented with two arrays of buffers and one +/// arrays of integers. +/// +/// For example, let X be a 2x3x4x5 tensor and let it have the following +/// 8 non-zero values: +/// ```text +/// X[0, 0, 0, 1] := 1 +/// X[0, 0, 0, 2] := 2 +/// X[0, 1, 0, 0] := 3 +/// X[0, 1, 0, 2] := 4 +/// X[0, 1, 1, 0] := 5 +/// X[1, 1, 1, 0] := 6 +/// X[1, 1, 1, 1] := 7 +/// X[1, 1, 1, 2] := 8 +/// ``` +/// As a prefix tree this would be represented as: +/// ```text +/// 0 1 +/// / \ | +/// 0 1 1 +/// / / \ | +/// 0 0 1 1 +/// /| /| | /| | +/// 1 2 0 2 0 0 1 2 +/// ``` +/// The type of values in indptrBuffers +/// indptrBuffers stores the sparsity structure. +/// Each two consecutive dimensions in a tensor correspond to a buffer in +/// indptrBuffers. A pair of consecutive values at `indptrBuffers[dim][i]` +/// and `indptrBuffers[dim][i + 1]` signify a range of nodes in +/// `indicesBuffers[dim + 1]` who are children of `indicesBuffers[dim][i]` node. +/// +/// For example, the indptrBuffers for the above X is: +/// ```text +/// indptrBuffer(X) = [ +/// [0, 2, 3], +/// [0, 1, 3, 4], +/// [0, 2, 4, 5, 8] +/// ]. +/// ``` +func (rcv *SparseTensorIndexCSF) IndptrBuffers(obj *Buffer, j int) bool { + o := flatbuffers.UOffsetT(rcv._tab.Offset(6)) + if o != 0 { + x := rcv._tab.Vector(o) + x += flatbuffers.UOffsetT(j) * 16 + obj.Init(rcv._tab.Bytes, x) + return true + } + return false +} + +func (rcv *SparseTensorIndexCSF) IndptrBuffersLength() int { + o := flatbuffers.UOffsetT(rcv._tab.Offset(6)) + if o != 0 { + return rcv._tab.VectorLen(o) + } + return 0 +} + +/// indptrBuffers stores the sparsity structure. +/// Each two consecutive dimensions in a tensor correspond to a buffer in +/// indptrBuffers. A pair of consecutive values at `indptrBuffers[dim][i]` +/// and `indptrBuffers[dim][i + 1]` signify a range of nodes in +/// `indicesBuffers[dim + 1]` who are children of `indicesBuffers[dim][i]` node. +/// +/// For example, the indptrBuffers for the above X is: +/// ```text +/// indptrBuffer(X) = [ +/// [0, 2, 3], +/// [0, 1, 3, 4], +/// [0, 2, 4, 5, 8] +/// ]. +/// ``` +/// The type of values in indicesBuffers +func (rcv *SparseTensorIndexCSF) IndicesType(obj *Int) *Int { + o := flatbuffers.UOffsetT(rcv._tab.Offset(8)) + if o != 0 { + x := rcv._tab.Indirect(o + rcv._tab.Pos) + if obj == nil { + obj = new(Int) + } + obj.Init(rcv._tab.Bytes, x) + return obj + } + return nil +} + +/// The type of values in indicesBuffers +/// indicesBuffers stores values of nodes. +/// Each tensor dimension corresponds to a buffer in indicesBuffers. +/// For example, the indicesBuffers for the above X is: +/// ```text +/// indicesBuffer(X) = [ +/// [0, 1], +/// [0, 1, 1], +/// [0, 0, 1, 1], +/// [1, 2, 0, 2, 0, 0, 1, 2] +/// ]. +/// ``` +func (rcv *SparseTensorIndexCSF) IndicesBuffers(obj *Buffer, j int) bool { + o := flatbuffers.UOffsetT(rcv._tab.Offset(10)) + if o != 0 { + x := rcv._tab.Vector(o) + x += flatbuffers.UOffsetT(j) * 16 + obj.Init(rcv._tab.Bytes, x) + return true + } + return false +} + +func (rcv *SparseTensorIndexCSF) IndicesBuffersLength() int { + o := flatbuffers.UOffsetT(rcv._tab.Offset(10)) + if o != 0 { + return rcv._tab.VectorLen(o) + } + return 0 +} + +/// indicesBuffers stores values of nodes. +/// Each tensor dimension corresponds to a buffer in indicesBuffers. +/// For example, the indicesBuffers for the above X is: +/// ```text +/// indicesBuffer(X) = [ +/// [0, 1], +/// [0, 1, 1], +/// [0, 0, 1, 1], +/// [1, 2, 0, 2, 0, 0, 1, 2] +/// ]. +/// ``` +/// axisOrder stores the sequence in which dimensions were traversed to +/// produce the prefix tree. +/// For example, the axisOrder for the above X is: +/// ```text +/// axisOrder(X) = [0, 1, 2, 3]. +/// ``` +func (rcv *SparseTensorIndexCSF) AxisOrder(j int) int32 { + o := flatbuffers.UOffsetT(rcv._tab.Offset(12)) + if o != 0 { + a := rcv._tab.Vector(o) + return rcv._tab.GetInt32(a + flatbuffers.UOffsetT(j*4)) + } + return 0 +} + +func (rcv *SparseTensorIndexCSF) AxisOrderLength() int { + o := flatbuffers.UOffsetT(rcv._tab.Offset(12)) + if o != 0 { + return rcv._tab.VectorLen(o) + } + return 0 +} + +/// axisOrder stores the sequence in which dimensions were traversed to +/// produce the prefix tree. +/// For example, the axisOrder for the above X is: +/// ```text +/// axisOrder(X) = [0, 1, 2, 3]. +/// ``` +func (rcv *SparseTensorIndexCSF) MutateAxisOrder(j int, n int32) bool { + o := flatbuffers.UOffsetT(rcv._tab.Offset(12)) + if o != 0 { + a := rcv._tab.Vector(o) + return rcv._tab.MutateInt32(a+flatbuffers.UOffsetT(j*4), n) + } + return false +} + +func SparseTensorIndexCSFStart(builder *flatbuffers.Builder) { + builder.StartObject(5) +} +func SparseTensorIndexCSFAddIndptrType(builder *flatbuffers.Builder, indptrType flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(indptrType), 0) +} +func SparseTensorIndexCSFAddIndptrBuffers(builder *flatbuffers.Builder, indptrBuffers flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(1, flatbuffers.UOffsetT(indptrBuffers), 0) +} +func SparseTensorIndexCSFStartIndptrBuffersVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT { + return builder.StartVector(16, numElems, 8) +} +func SparseTensorIndexCSFAddIndicesType(builder *flatbuffers.Builder, indicesType flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(2, flatbuffers.UOffsetT(indicesType), 0) +} +func SparseTensorIndexCSFAddIndicesBuffers(builder *flatbuffers.Builder, indicesBuffers flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(3, flatbuffers.UOffsetT(indicesBuffers), 0) +} +func SparseTensorIndexCSFStartIndicesBuffersVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT { + return builder.StartVector(16, numElems, 8) +} +func SparseTensorIndexCSFAddAxisOrder(builder *flatbuffers.Builder, axisOrder flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(4, flatbuffers.UOffsetT(axisOrder), 0) +} +func SparseTensorIndexCSFStartAxisOrderVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT { + return builder.StartVector(4, numElems, 4) +} +func SparseTensorIndexCSFEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Struct_.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Struct_.go new file mode 100644 index 000000000..427e70603 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Struct_.go @@ -0,0 +1,53 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +/// A Struct_ in the flatbuffer metadata is the same as an Arrow Struct +/// (according to the physical memory layout). We used Struct_ here as +/// Struct is a reserved word in Flatbuffers +type Struct_ struct { + _tab flatbuffers.Table +} + +func GetRootAsStruct_(buf []byte, offset flatbuffers.UOffsetT) *Struct_ { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &Struct_{} + x.Init(buf, n+offset) + return x +} + +func (rcv *Struct_) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *Struct_) Table() flatbuffers.Table { + return rcv._tab +} + +func Struct_Start(builder *flatbuffers.Builder) { + builder.StartObject(0) +} +func Struct_End(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Tensor.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Tensor.go new file mode 100644 index 000000000..39d70e351 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Tensor.go @@ -0,0 +1,163 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +type Tensor struct { + _tab flatbuffers.Table +} + +func GetRootAsTensor(buf []byte, offset flatbuffers.UOffsetT) *Tensor { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &Tensor{} + x.Init(buf, n+offset) + return x +} + +func (rcv *Tensor) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *Tensor) Table() flatbuffers.Table { + return rcv._tab +} + +func (rcv *Tensor) TypeType() Type { + o := flatbuffers.UOffsetT(rcv._tab.Offset(4)) + if o != 0 { + return Type(rcv._tab.GetByte(o + rcv._tab.Pos)) + } + return 0 +} + +func (rcv *Tensor) MutateTypeType(n Type) bool { + return rcv._tab.MutateByteSlot(4, byte(n)) +} + +/// The type of data contained in a value cell. Currently only fixed-width +/// value types are supported, no strings or nested types +func (rcv *Tensor) Type(obj *flatbuffers.Table) bool { + o := flatbuffers.UOffsetT(rcv._tab.Offset(6)) + if o != 0 { + rcv._tab.Union(obj, o) + return true + } + return false +} + +/// The type of data contained in a value cell. Currently only fixed-width +/// value types are supported, no strings or nested types +/// The dimensions of the tensor, optionally named +func (rcv *Tensor) Shape(obj *TensorDim, j int) bool { + o := flatbuffers.UOffsetT(rcv._tab.Offset(8)) + if o != 0 { + x := rcv._tab.Vector(o) + x += flatbuffers.UOffsetT(j) * 4 + x = rcv._tab.Indirect(x) + obj.Init(rcv._tab.Bytes, x) + return true + } + return false +} + +func (rcv *Tensor) ShapeLength() int { + o := flatbuffers.UOffsetT(rcv._tab.Offset(8)) + if o != 0 { + return rcv._tab.VectorLen(o) + } + return 0 +} + +/// The dimensions of the tensor, optionally named +/// Non-negative byte offsets to advance one value cell along each dimension +/// If omitted, default to row-major order (C-like). +func (rcv *Tensor) Strides(j int) int64 { + o := flatbuffers.UOffsetT(rcv._tab.Offset(10)) + if o != 0 { + a := rcv._tab.Vector(o) + return rcv._tab.GetInt64(a + flatbuffers.UOffsetT(j*8)) + } + return 0 +} + +func (rcv *Tensor) StridesLength() int { + o := flatbuffers.UOffsetT(rcv._tab.Offset(10)) + if o != 0 { + return rcv._tab.VectorLen(o) + } + return 0 +} + +/// Non-negative byte offsets to advance one value cell along each dimension +/// If omitted, default to row-major order (C-like). +func (rcv *Tensor) MutateStrides(j int, n int64) bool { + o := flatbuffers.UOffsetT(rcv._tab.Offset(10)) + if o != 0 { + a := rcv._tab.Vector(o) + return rcv._tab.MutateInt64(a+flatbuffers.UOffsetT(j*8), n) + } + return false +} + +/// The location and size of the tensor's data +func (rcv *Tensor) Data(obj *Buffer) *Buffer { + o := flatbuffers.UOffsetT(rcv._tab.Offset(12)) + if o != 0 { + x := o + rcv._tab.Pos + if obj == nil { + obj = new(Buffer) + } + obj.Init(rcv._tab.Bytes, x) + return obj + } + return nil +} + +/// The location and size of the tensor's data +func TensorStart(builder *flatbuffers.Builder) { + builder.StartObject(5) +} +func TensorAddTypeType(builder *flatbuffers.Builder, typeType Type) { + builder.PrependByteSlot(0, byte(typeType), 0) +} +func TensorAddType(builder *flatbuffers.Builder, type_ flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(1, flatbuffers.UOffsetT(type_), 0) +} +func TensorAddShape(builder *flatbuffers.Builder, shape flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(2, flatbuffers.UOffsetT(shape), 0) +} +func TensorStartShapeVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT { + return builder.StartVector(4, numElems, 4) +} +func TensorAddStrides(builder *flatbuffers.Builder, strides flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(3, flatbuffers.UOffsetT(strides), 0) +} +func TensorStartStridesVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT { + return builder.StartVector(8, numElems, 8) +} +func TensorAddData(builder *flatbuffers.Builder, data flatbuffers.UOffsetT) { + builder.PrependStructSlot(4, flatbuffers.UOffsetT(data), 0) +} +func TensorEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/TensorDim.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/TensorDim.go new file mode 100644 index 000000000..14b821208 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/TensorDim.go @@ -0,0 +1,83 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +/// ---------------------------------------------------------------------- +/// Data structures for dense tensors +/// Shape data for a single axis in a tensor +type TensorDim struct { + _tab flatbuffers.Table +} + +func GetRootAsTensorDim(buf []byte, offset flatbuffers.UOffsetT) *TensorDim { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &TensorDim{} + x.Init(buf, n+offset) + return x +} + +func (rcv *TensorDim) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *TensorDim) Table() flatbuffers.Table { + return rcv._tab +} + +/// Length of dimension +func (rcv *TensorDim) Size() int64 { + o := flatbuffers.UOffsetT(rcv._tab.Offset(4)) + if o != 0 { + return rcv._tab.GetInt64(o + rcv._tab.Pos) + } + return 0 +} + +/// Length of dimension +func (rcv *TensorDim) MutateSize(n int64) bool { + return rcv._tab.MutateInt64Slot(4, n) +} + +/// Name of the dimension, optional +func (rcv *TensorDim) Name() []byte { + o := flatbuffers.UOffsetT(rcv._tab.Offset(6)) + if o != 0 { + return rcv._tab.ByteVector(o + rcv._tab.Pos) + } + return nil +} + +/// Name of the dimension, optional +func TensorDimStart(builder *flatbuffers.Builder) { + builder.StartObject(2) +} +func TensorDimAddSize(builder *flatbuffers.Builder, size int64) { + builder.PrependInt64Slot(0, size, 0) +} +func TensorDimAddName(builder *flatbuffers.Builder, name flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(1, flatbuffers.UOffsetT(name), 0) +} +func TensorDimEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Time.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Time.go new file mode 100644 index 000000000..2fb6e4c11 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Time.go @@ -0,0 +1,94 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +/// Time is either a 32-bit or 64-bit signed integer type representing an +/// elapsed time since midnight, stored in either of four units: seconds, +/// milliseconds, microseconds or nanoseconds. +/// +/// The integer `bitWidth` depends on the `unit` and must be one of the following: +/// * SECOND and MILLISECOND: 32 bits +/// * MICROSECOND and NANOSECOND: 64 bits +/// +/// The allowed values are between 0 (inclusive) and 86400 (=24*60*60) seconds +/// (exclusive), adjusted for the time unit (for example, up to 86400000 +/// exclusive for the MILLISECOND unit). +/// This definition doesn't allow for leap seconds. Time values from +/// measurements with leap seconds will need to be corrected when ingesting +/// into Arrow (for example by replacing the value 86400 with 86399). +type Time struct { + _tab flatbuffers.Table +} + +func GetRootAsTime(buf []byte, offset flatbuffers.UOffsetT) *Time { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &Time{} + x.Init(buf, n+offset) + return x +} + +func (rcv *Time) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *Time) Table() flatbuffers.Table { + return rcv._tab +} + +func (rcv *Time) Unit() TimeUnit { + o := flatbuffers.UOffsetT(rcv._tab.Offset(4)) + if o != 0 { + return TimeUnit(rcv._tab.GetInt16(o + rcv._tab.Pos)) + } + return 1 +} + +func (rcv *Time) MutateUnit(n TimeUnit) bool { + return rcv._tab.MutateInt16Slot(4, int16(n)) +} + +func (rcv *Time) BitWidth() int32 { + o := flatbuffers.UOffsetT(rcv._tab.Offset(6)) + if o != 0 { + return rcv._tab.GetInt32(o + rcv._tab.Pos) + } + return 32 +} + +func (rcv *Time) MutateBitWidth(n int32) bool { + return rcv._tab.MutateInt32Slot(6, n) +} + +func TimeStart(builder *flatbuffers.Builder) { + builder.StartObject(2) +} +func TimeAddUnit(builder *flatbuffers.Builder, unit TimeUnit) { + builder.PrependInt16Slot(0, int16(unit), 1) +} +func TimeAddBitWidth(builder *flatbuffers.Builder, bitWidth int32) { + builder.PrependInt32Slot(1, bitWidth, 32) +} +func TimeEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/TimeUnit.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/TimeUnit.go new file mode 100644 index 000000000..df14ece4f --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/TimeUnit.go @@ -0,0 +1,51 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import "strconv" + +type TimeUnit int16 + +const ( + TimeUnitSECOND TimeUnit = 0 + TimeUnitMILLISECOND TimeUnit = 1 + TimeUnitMICROSECOND TimeUnit = 2 + TimeUnitNANOSECOND TimeUnit = 3 +) + +var EnumNamesTimeUnit = map[TimeUnit]string{ + TimeUnitSECOND: "SECOND", + TimeUnitMILLISECOND: "MILLISECOND", + TimeUnitMICROSECOND: "MICROSECOND", + TimeUnitNANOSECOND: "NANOSECOND", +} + +var EnumValuesTimeUnit = map[string]TimeUnit{ + "SECOND": TimeUnitSECOND, + "MILLISECOND": TimeUnitMILLISECOND, + "MICROSECOND": TimeUnitMICROSECOND, + "NANOSECOND": TimeUnitNANOSECOND, +} + +func (v TimeUnit) String() string { + if s, ok := EnumNamesTimeUnit[v]; ok { + return s + } + return "TimeUnit(" + strconv.FormatInt(int64(v), 10) + ")" +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Timestamp.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Timestamp.go new file mode 100644 index 000000000..f53211455 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Timestamp.go @@ -0,0 +1,201 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +/// Timestamp is a 64-bit signed integer representing an elapsed time since a +/// fixed epoch, stored in either of four units: seconds, milliseconds, +/// microseconds or nanoseconds, and is optionally annotated with a timezone. +/// +/// Timestamp values do not include any leap seconds (in other words, all +/// days are considered 86400 seconds long). +/// +/// Timestamps with a non-empty timezone +/// ------------------------------------ +/// +/// If a Timestamp column has a non-empty timezone value, its epoch is +/// 1970-01-01 00:00:00 (January 1st 1970, midnight) in the *UTC* timezone +/// (the Unix epoch), regardless of the Timestamp's own timezone. +/// +/// Therefore, timestamp values with a non-empty timezone correspond to +/// physical points in time together with some additional information about +/// how the data was obtained and/or how to display it (the timezone). +/// +/// For example, the timestamp value 0 with the timezone string "Europe/Paris" +/// corresponds to "January 1st 1970, 00h00" in the UTC timezone, but the +/// application may prefer to display it as "January 1st 1970, 01h00" in +/// the Europe/Paris timezone (which is the same physical point in time). +/// +/// One consequence is that timestamp values with a non-empty timezone +/// can be compared and ordered directly, since they all share the same +/// well-known point of reference (the Unix epoch). +/// +/// Timestamps with an unset / empty timezone +/// ----------------------------------------- +/// +/// If a Timestamp column has no timezone value, its epoch is +/// 1970-01-01 00:00:00 (January 1st 1970, midnight) in an *unknown* timezone. +/// +/// Therefore, timestamp values without a timezone cannot be meaningfully +/// interpreted as physical points in time, but only as calendar / clock +/// indications ("wall clock time") in an unspecified timezone. +/// +/// For example, the timestamp value 0 with an empty timezone string +/// corresponds to "January 1st 1970, 00h00" in an unknown timezone: there +/// is not enough information to interpret it as a well-defined physical +/// point in time. +/// +/// One consequence is that timestamp values without a timezone cannot +/// be reliably compared or ordered, since they may have different points of +/// reference. In particular, it is *not* possible to interpret an unset +/// or empty timezone as the same as "UTC". +/// +/// Conversion between timezones +/// ---------------------------- +/// +/// If a Timestamp column has a non-empty timezone, changing the timezone +/// to a different non-empty value is a metadata-only operation: +/// the timestamp values need not change as their point of reference remains +/// the same (the Unix epoch). +/// +/// However, if a Timestamp column has no timezone value, changing it to a +/// non-empty value requires to think about the desired semantics. +/// One possibility is to assume that the original timestamp values are +/// relative to the epoch of the timezone being set; timestamp values should +/// then adjusted to the Unix epoch (for example, changing the timezone from +/// empty to "Europe/Paris" would require converting the timestamp values +/// from "Europe/Paris" to "UTC", which seems counter-intuitive but is +/// nevertheless correct). +/// +/// Guidelines for encoding data from external libraries +/// ---------------------------------------------------- +/// +/// Date & time libraries often have multiple different data types for temporal +/// data. In order to ease interoperability between different implementations the +/// Arrow project has some recommendations for encoding these types into a Timestamp +/// column. +/// +/// An "instant" represents a physical point in time that has no relevant timezone +/// (for example, astronomical data). To encode an instant, use a Timestamp with +/// the timezone string set to "UTC", and make sure the Timestamp values +/// are relative to the UTC epoch (January 1st 1970, midnight). +/// +/// A "zoned date-time" represents a physical point in time annotated with an +/// informative timezone (for example, the timezone in which the data was +/// recorded). To encode a zoned date-time, use a Timestamp with the timezone +/// string set to the name of the timezone, and make sure the Timestamp values +/// are relative to the UTC epoch (January 1st 1970, midnight). +/// +/// (There is some ambiguity between an instant and a zoned date-time with the +/// UTC timezone. Both of these are stored the same in Arrow. Typically, +/// this distinction does not matter. If it does, then an application should +/// use custom metadata or an extension type to distinguish between the two cases.) +/// +/// An "offset date-time" represents a physical point in time combined with an +/// explicit offset from UTC. To encode an offset date-time, use a Timestamp +/// with the timezone string set to the numeric timezone offset string +/// (e.g. "+03:00"), and make sure the Timestamp values are relative to +/// the UTC epoch (January 1st 1970, midnight). +/// +/// A "naive date-time" (also called "local date-time" in some libraries) +/// represents a wall clock time combined with a calendar date, but with +/// no indication of how to map this information to a physical point in time. +/// Naive date-times must be handled with care because of this missing +/// information, and also because daylight saving time (DST) may make +/// some values ambiguous or non-existent. A naive date-time may be +/// stored as a struct with Date and Time fields. However, it may also be +/// encoded into a Timestamp column with an empty timezone. The timestamp +/// values should be computed "as if" the timezone of the date-time values +/// was UTC; for example, the naive date-time "January 1st 1970, 00h00" would +/// be encoded as timestamp value 0. +type Timestamp struct { + _tab flatbuffers.Table +} + +func GetRootAsTimestamp(buf []byte, offset flatbuffers.UOffsetT) *Timestamp { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &Timestamp{} + x.Init(buf, n+offset) + return x +} + +func (rcv *Timestamp) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *Timestamp) Table() flatbuffers.Table { + return rcv._tab +} + +func (rcv *Timestamp) Unit() TimeUnit { + o := flatbuffers.UOffsetT(rcv._tab.Offset(4)) + if o != 0 { + return TimeUnit(rcv._tab.GetInt16(o + rcv._tab.Pos)) + } + return 0 +} + +func (rcv *Timestamp) MutateUnit(n TimeUnit) bool { + return rcv._tab.MutateInt16Slot(4, int16(n)) +} + +/// The timezone is an optional string indicating the name of a timezone, +/// one of: +/// +/// * As used in the Olson timezone database (the "tz database" or +/// "tzdata"), such as "America/New_York". +/// * An absolute timezone offset of the form "+XX:XX" or "-XX:XX", +/// such as "+07:30". +/// +/// Whether a timezone string is present indicates different semantics about +/// the data (see above). +func (rcv *Timestamp) Timezone() []byte { + o := flatbuffers.UOffsetT(rcv._tab.Offset(6)) + if o != 0 { + return rcv._tab.ByteVector(o + rcv._tab.Pos) + } + return nil +} + +/// The timezone is an optional string indicating the name of a timezone, +/// one of: +/// +/// * As used in the Olson timezone database (the "tz database" or +/// "tzdata"), such as "America/New_York". +/// * An absolute timezone offset of the form "+XX:XX" or "-XX:XX", +/// such as "+07:30". +/// +/// Whether a timezone string is present indicates different semantics about +/// the data (see above). +func TimestampStart(builder *flatbuffers.Builder) { + builder.StartObject(2) +} +func TimestampAddUnit(builder *flatbuffers.Builder, unit TimeUnit) { + builder.PrependInt16Slot(0, int16(unit), 0) +} +func TimestampAddTimezone(builder *flatbuffers.Builder, timezone flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(1, flatbuffers.UOffsetT(timezone), 0) +} +func TimestampEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Type.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Type.go new file mode 100644 index 000000000..ab2bce9c6 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Type.go @@ -0,0 +1,123 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import "strconv" + +/// ---------------------------------------------------------------------- +/// Top-level Type value, enabling extensible type-specific metadata. We can +/// add new logical types to Type without breaking backwards compatibility +type Type byte + +const ( + TypeNONE Type = 0 + TypeNull Type = 1 + TypeInt Type = 2 + TypeFloatingPoint Type = 3 + TypeBinary Type = 4 + TypeUtf8 Type = 5 + TypeBool Type = 6 + TypeDecimal Type = 7 + TypeDate Type = 8 + TypeTime Type = 9 + TypeTimestamp Type = 10 + TypeInterval Type = 11 + TypeList Type = 12 + TypeStruct_ Type = 13 + TypeUnion Type = 14 + TypeFixedSizeBinary Type = 15 + TypeFixedSizeList Type = 16 + TypeMap Type = 17 + TypeDuration Type = 18 + TypeLargeBinary Type = 19 + TypeLargeUtf8 Type = 20 + TypeLargeList Type = 21 + TypeRunEndEncoded Type = 22 + TypeBinaryView Type = 23 + TypeUtf8View Type = 24 + TypeListView Type = 25 + TypeLargeListView Type = 26 +) + +var EnumNamesType = map[Type]string{ + TypeNONE: "NONE", + TypeNull: "Null", + TypeInt: "Int", + TypeFloatingPoint: "FloatingPoint", + TypeBinary: "Binary", + TypeUtf8: "Utf8", + TypeBool: "Bool", + TypeDecimal: "Decimal", + TypeDate: "Date", + TypeTime: "Time", + TypeTimestamp: "Timestamp", + TypeInterval: "Interval", + TypeList: "List", + TypeStruct_: "Struct_", + TypeUnion: "Union", + TypeFixedSizeBinary: "FixedSizeBinary", + TypeFixedSizeList: "FixedSizeList", + TypeMap: "Map", + TypeDuration: "Duration", + TypeLargeBinary: "LargeBinary", + TypeLargeUtf8: "LargeUtf8", + TypeLargeList: "LargeList", + TypeRunEndEncoded: "RunEndEncoded", + TypeBinaryView: "BinaryView", + TypeUtf8View: "Utf8View", + TypeListView: "ListView", + TypeLargeListView: "LargeListView", +} + +var EnumValuesType = map[string]Type{ + "NONE": TypeNONE, + "Null": TypeNull, + "Int": TypeInt, + "FloatingPoint": TypeFloatingPoint, + "Binary": TypeBinary, + "Utf8": TypeUtf8, + "Bool": TypeBool, + "Decimal": TypeDecimal, + "Date": TypeDate, + "Time": TypeTime, + "Timestamp": TypeTimestamp, + "Interval": TypeInterval, + "List": TypeList, + "Struct_": TypeStruct_, + "Union": TypeUnion, + "FixedSizeBinary": TypeFixedSizeBinary, + "FixedSizeList": TypeFixedSizeList, + "Map": TypeMap, + "Duration": TypeDuration, + "LargeBinary": TypeLargeBinary, + "LargeUtf8": TypeLargeUtf8, + "LargeList": TypeLargeList, + "RunEndEncoded": TypeRunEndEncoded, + "BinaryView": TypeBinaryView, + "Utf8View": TypeUtf8View, + "ListView": TypeListView, + "LargeListView": TypeLargeListView, +} + +func (v Type) String() string { + if s, ok := EnumNamesType[v]; ok { + return s + } + return "Type(" + strconv.FormatInt(int64(v), 10) + ")" +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Union.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Union.go new file mode 100644 index 000000000..e34121d47 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Union.go @@ -0,0 +1,101 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +/// A union is a complex type with children in Field +/// By default ids in the type vector refer to the offsets in the children +/// optionally typeIds provides an indirection between the child offset and the type id +/// for each child `typeIds[offset]` is the id used in the type vector +type Union struct { + _tab flatbuffers.Table +} + +func GetRootAsUnion(buf []byte, offset flatbuffers.UOffsetT) *Union { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &Union{} + x.Init(buf, n+offset) + return x +} + +func (rcv *Union) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *Union) Table() flatbuffers.Table { + return rcv._tab +} + +func (rcv *Union) Mode() UnionMode { + o := flatbuffers.UOffsetT(rcv._tab.Offset(4)) + if o != 0 { + return UnionMode(rcv._tab.GetInt16(o + rcv._tab.Pos)) + } + return 0 +} + +func (rcv *Union) MutateMode(n UnionMode) bool { + return rcv._tab.MutateInt16Slot(4, int16(n)) +} + +func (rcv *Union) TypeIds(j int) int32 { + o := flatbuffers.UOffsetT(rcv._tab.Offset(6)) + if o != 0 { + a := rcv._tab.Vector(o) + return rcv._tab.GetInt32(a + flatbuffers.UOffsetT(j*4)) + } + return 0 +} + +func (rcv *Union) TypeIdsLength() int { + o := flatbuffers.UOffsetT(rcv._tab.Offset(6)) + if o != 0 { + return rcv._tab.VectorLen(o) + } + return 0 +} + +func (rcv *Union) MutateTypeIds(j int, n int32) bool { + o := flatbuffers.UOffsetT(rcv._tab.Offset(6)) + if o != 0 { + a := rcv._tab.Vector(o) + return rcv._tab.MutateInt32(a+flatbuffers.UOffsetT(j*4), n) + } + return false +} + +func UnionStart(builder *flatbuffers.Builder) { + builder.StartObject(2) +} +func UnionAddMode(builder *flatbuffers.Builder, mode UnionMode) { + builder.PrependInt16Slot(0, int16(mode), 0) +} +func UnionAddTypeIds(builder *flatbuffers.Builder, typeIds flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(1, flatbuffers.UOffsetT(typeIds), 0) +} +func UnionStartTypeIdsVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT { + return builder.StartVector(4, numElems, 4) +} +func UnionEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/UnionMode.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/UnionMode.go new file mode 100644 index 000000000..357c1f3cb --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/UnionMode.go @@ -0,0 +1,45 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import "strconv" + +type UnionMode int16 + +const ( + UnionModeSparse UnionMode = 0 + UnionModeDense UnionMode = 1 +) + +var EnumNamesUnionMode = map[UnionMode]string{ + UnionModeSparse: "Sparse", + UnionModeDense: "Dense", +} + +var EnumValuesUnionMode = map[string]UnionMode{ + "Sparse": UnionModeSparse, + "Dense": UnionModeDense, +} + +func (v UnionMode) String() string { + if s, ok := EnumNamesUnionMode[v]; ok { + return s + } + return "UnionMode(" + strconv.FormatInt(int64(v), 10) + ")" +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Utf8.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Utf8.go new file mode 100644 index 000000000..4ff365a37 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Utf8.go @@ -0,0 +1,51 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +/// Unicode with UTF-8 encoding +type Utf8 struct { + _tab flatbuffers.Table +} + +func GetRootAsUtf8(buf []byte, offset flatbuffers.UOffsetT) *Utf8 { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &Utf8{} + x.Init(buf, n+offset) + return x +} + +func (rcv *Utf8) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *Utf8) Table() flatbuffers.Table { + return rcv._tab +} + +func Utf8Start(builder *flatbuffers.Builder) { + builder.StartObject(0) +} +func Utf8End(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Utf8View.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Utf8View.go new file mode 100644 index 000000000..9cf821490 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/flatbuf/Utf8View.go @@ -0,0 +1,57 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by the FlatBuffers compiler. DO NOT EDIT. + +package flatbuf + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) + +/// Logically the same as Utf8, but the internal representation uses a view +/// struct that contains the string length and either the string's entire data +/// inline (for small strings) or an inlined prefix, an index of another buffer, +/// and an offset pointing to a slice in that buffer (for non-small strings). +/// +/// Since it uses a variable number of data buffers, each Field with this type +/// must have a corresponding entry in `variadicBufferCounts`. +type Utf8View struct { + _tab flatbuffers.Table +} + +func GetRootAsUtf8View(buf []byte, offset flatbuffers.UOffsetT) *Utf8View { + n := flatbuffers.GetUOffsetT(buf[offset:]) + x := &Utf8View{} + x.Init(buf, n+offset) + return x +} + +func (rcv *Utf8View) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *Utf8View) Table() flatbuffers.Table { + return rcv._tab +} + +func Utf8ViewStart(builder *flatbuffers.Builder) { + builder.StartObject(0) +} +func Utf8ViewEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { + return builder.EndObject() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/internal/utils.go b/vendor/github.com/apache/arrow/go/v14/arrow/internal/utils.go new file mode 100644 index 000000000..265f030df --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/internal/utils.go @@ -0,0 +1,47 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package internal + +import ( + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/internal/flatbuf" +) + +const CurMetadataVersion = flatbuf.MetadataVersionV5 + +// DefaultHasValidityBitmap is a convenience function equivalent to +// calling HasValidityBitmap with CurMetadataVersion. +func DefaultHasValidityBitmap(id arrow.Type) bool { return HasValidityBitmap(id, CurMetadataVersion) } + +// HasValidityBitmap returns whether the given type at the provided version is +// expected to have a validity bitmap in it's representation. +// +// Typically this is necessary because of the change between V4 and V5 +// where union types no longer have validity bitmaps. +func HasValidityBitmap(id arrow.Type, version flatbuf.MetadataVersion) bool { + // in <=V4 Null types had no validity bitmap + // in >=V5 Null and Union types have no validity bitmap + if version < flatbuf.MetadataVersionV5 { + return id != arrow.NULL + } + + switch id { + case arrow.NULL, arrow.DENSE_UNION, arrow.SPARSE_UNION, arrow.RUN_END_ENCODED: + return false + } + return true +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/ipc/compression.go b/vendor/github.com/apache/arrow/go/v14/arrow/ipc/compression.go new file mode 100644 index 000000000..73fb91650 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/ipc/compression.go @@ -0,0 +1,135 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ipc + +import ( + "io" + + "github.com/apache/arrow/go/v14/arrow/internal/debug" + "github.com/apache/arrow/go/v14/arrow/internal/flatbuf" + "github.com/apache/arrow/go/v14/arrow/memory" + "github.com/klauspost/compress/zstd" + "github.com/pierrec/lz4/v4" +) + +type compressor interface { + MaxCompressedLen(n int) int + Reset(io.Writer) + io.WriteCloser + Type() flatbuf.CompressionType +} + +type lz4Compressor struct { + *lz4.Writer +} + +func (lz4Compressor) MaxCompressedLen(n int) int { + return lz4.CompressBlockBound(n) +} + +func (lz4Compressor) Type() flatbuf.CompressionType { + return flatbuf.CompressionTypeLZ4_FRAME +} + +type zstdCompressor struct { + *zstd.Encoder +} + +// from zstd.h, ZSTD_COMPRESSBOUND +func (zstdCompressor) MaxCompressedLen(len int) int { + debug.Assert(len >= 0, "MaxCompressedLen called with len less than 0") + extra := uint((uint(128<<10) - uint(len)) >> 11) + if len >= (128 << 10) { + extra = 0 + } + return int(uint(len+(len>>8)) + extra) +} + +func (zstdCompressor) Type() flatbuf.CompressionType { + return flatbuf.CompressionTypeZSTD +} + +func getCompressor(codec flatbuf.CompressionType) compressor { + switch codec { + case flatbuf.CompressionTypeLZ4_FRAME: + w := lz4.NewWriter(nil) + // options here chosen in order to match the C++ implementation + w.Apply(lz4.ChecksumOption(false), lz4.BlockSizeOption(lz4.Block64Kb)) + return &lz4Compressor{w} + case flatbuf.CompressionTypeZSTD: + enc, err := zstd.NewWriter(nil) + if err != nil { + panic(err) + } + return zstdCompressor{enc} + } + return nil +} + +type decompressor interface { + io.Reader + Reset(io.Reader) + Close() +} + +type zstdDecompressor struct { + *zstd.Decoder +} + +func (z *zstdDecompressor) Reset(r io.Reader) { + if err := z.Decoder.Reset(r); err != nil { + panic(err) + } +} + +func (z *zstdDecompressor) Close() { + z.Decoder.Close() +} + +type lz4Decompressor struct { + *lz4.Reader +} + +func (z *lz4Decompressor) Close() {} + +func getDecompressor(codec flatbuf.CompressionType) decompressor { + switch codec { + case flatbuf.CompressionTypeLZ4_FRAME: + return &lz4Decompressor{lz4.NewReader(nil)} + case flatbuf.CompressionTypeZSTD: + dec, err := zstd.NewReader(nil) + if err != nil { + panic(err) + } + return &zstdDecompressor{dec} + } + return nil +} + +type bufferWriter struct { + buf *memory.Buffer + pos int +} + +func (bw *bufferWriter) Write(p []byte) (n int, err error) { + if bw.pos+len(p) >= bw.buf.Cap() { + bw.buf.Reserve(bw.pos + len(p)) + } + n = copy(bw.buf.Buf()[bw.pos:], p) + bw.pos += n + return +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/ipc/endian_swap.go b/vendor/github.com/apache/arrow/go/v14/arrow/ipc/endian_swap.go new file mode 100644 index 000000000..d98fec108 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/ipc/endian_swap.go @@ -0,0 +1,162 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ipc + +import ( + "errors" + "math/bits" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/array" + "github.com/apache/arrow/go/v14/arrow/memory" +) + +// swap the endianness of the array's buffers as needed in-place to save +// the cost of reallocation. +// +// assumes that nested data buffers are never re-used, if an *array.Data +// child is re-used among the children or the dictionary then this might +// end up double-swapping (putting it back into the original endianness). +// if it is needed to support re-using the buffers, then this can be +// re-factored to instead return a NEW array.Data object with newly +// allocated buffers, rather than doing it in place. +// +// For now this is intended to be used by the IPC readers after loading +// arrays from an IPC message which currently is guaranteed to not re-use +// buffers between arrays. +func swapEndianArrayData(data *array.Data) error { + if data.Offset() != 0 { + return errors.New("unsupported data format: data.offset != 0") + } + if err := swapType(data.DataType(), data); err != nil { + return err + } + return swapChildren(data.Children()) +} + +func swapChildren(children []arrow.ArrayData) (err error) { + for i := range children { + if err = swapEndianArrayData(children[i].(*array.Data)); err != nil { + break + } + } + return +} + +func swapType(dt arrow.DataType, data *array.Data) (err error) { + switch dt.ID() { + case arrow.BINARY, arrow.STRING: + swapOffsets(1, 32, data) + return + case arrow.LARGE_BINARY, arrow.LARGE_STRING: + swapOffsets(1, 64, data) + return + case arrow.NULL, arrow.BOOL, arrow.INT8, arrow.UINT8, + arrow.FIXED_SIZE_BINARY, arrow.FIXED_SIZE_LIST, arrow.STRUCT: + return + } + + switch dt := dt.(type) { + case *arrow.Decimal128Type: + rawdata := arrow.Uint64Traits.CastFromBytes(data.Buffers()[1].Bytes()) + length := data.Buffers()[1].Len() / arrow.Decimal128SizeBytes + for i := 0; i < length; i++ { + idx := i * 2 + tmp := bits.ReverseBytes64(rawdata[idx]) + rawdata[idx] = bits.ReverseBytes64(rawdata[idx+1]) + rawdata[idx+1] = tmp + } + case *arrow.Decimal256Type: + rawdata := arrow.Uint64Traits.CastFromBytes(data.Buffers()[1].Bytes()) + length := data.Buffers()[1].Len() / arrow.Decimal256SizeBytes + for i := 0; i < length; i++ { + idx := i * 4 + tmp0 := bits.ReverseBytes64(rawdata[idx]) + tmp1 := bits.ReverseBytes64(rawdata[idx+1]) + tmp2 := bits.ReverseBytes64(rawdata[idx+2]) + rawdata[idx] = bits.ReverseBytes64(rawdata[idx+3]) + rawdata[idx+1] = tmp2 + rawdata[idx+2] = tmp1 + rawdata[idx+3] = tmp0 + } + case arrow.UnionType: + if dt.Mode() == arrow.DenseMode { + swapOffsets(2, 32, data) + } + case *arrow.ListType: + swapOffsets(1, 32, data) + case *arrow.LargeListType: + swapOffsets(1, 64, data) + case *arrow.MapType: + swapOffsets(1, 32, data) + case *arrow.DayTimeIntervalType: + byteSwapBuffer(32, data.Buffers()[1]) + case *arrow.MonthDayNanoIntervalType: + rawdata := arrow.MonthDayNanoIntervalTraits.CastFromBytes(data.Buffers()[1].Bytes()) + for i, tmp := range rawdata { + rawdata[i].Days = int32(bits.ReverseBytes32(uint32(tmp.Days))) + rawdata[i].Months = int32(bits.ReverseBytes32(uint32(tmp.Months))) + rawdata[i].Nanoseconds = int64(bits.ReverseBytes64(uint64(tmp.Nanoseconds))) + } + case arrow.ExtensionType: + return swapType(dt.StorageType(), data) + case *arrow.DictionaryType: + // dictionary itself was already swapped in ReadDictionary calls + return swapType(dt.IndexType, data) + case arrow.FixedWidthDataType: + byteSwapBuffer(dt.BitWidth(), data.Buffers()[1]) + } + return +} + +// this can get called on an invalid Array Data object by the IPC reader, +// so we won't rely on the data.length and will instead rely on the buffer's +// own size instead. +func byteSwapBuffer(bw int, buf *memory.Buffer) { + if bw == 1 || buf == nil { + // if byte width == 1, no need to swap anything + return + } + + switch bw { + case 16: + data := arrow.Uint16Traits.CastFromBytes(buf.Bytes()) + for i := range data { + data[i] = bits.ReverseBytes16(data[i]) + } + case 32: + data := arrow.Uint32Traits.CastFromBytes(buf.Bytes()) + for i := range data { + data[i] = bits.ReverseBytes32(data[i]) + } + case 64: + data := arrow.Uint64Traits.CastFromBytes(buf.Bytes()) + for i := range data { + data[i] = bits.ReverseBytes64(data[i]) + } + } +} + +func swapOffsets(index int, bitWidth int, data *array.Data) { + if data.Buffers()[index] == nil || data.Buffers()[index].Len() == 0 { + return + } + + // other than unions, offset has one more element than the data.length + // don't yet implement large types, so hardcode 32bit offsets for now + byteSwapBuffer(bitWidth, data.Buffers()[index]) +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/ipc/file_reader.go b/vendor/github.com/apache/arrow/go/v14/arrow/ipc/file_reader.go new file mode 100644 index 000000000..10cb2cae7 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/ipc/file_reader.go @@ -0,0 +1,751 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ipc + +import ( + "bytes" + "encoding/binary" + "errors" + "fmt" + "io" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/array" + "github.com/apache/arrow/go/v14/arrow/bitutil" + "github.com/apache/arrow/go/v14/arrow/endian" + "github.com/apache/arrow/go/v14/arrow/internal" + "github.com/apache/arrow/go/v14/arrow/internal/dictutils" + "github.com/apache/arrow/go/v14/arrow/internal/flatbuf" + "github.com/apache/arrow/go/v14/arrow/memory" +) + +// FileReader is an Arrow file reader. +type FileReader struct { + r ReadAtSeeker + + footer struct { + offset int64 + buffer *memory.Buffer + data *flatbuf.Footer + } + + // fields dictTypeMap + memo dictutils.Memo + + schema *arrow.Schema + record arrow.Record + + irec int // current record index. used for the arrio.Reader interface + err error // last error + + mem memory.Allocator + swapEndianness bool +} + +// NewFileReader opens an Arrow file using the provided reader r. +func NewFileReader(r ReadAtSeeker, opts ...Option) (*FileReader, error) { + var ( + cfg = newConfig(opts...) + err error + + f = FileReader{ + r: r, + memo: dictutils.NewMemo(), + mem: cfg.alloc, + } + ) + + if cfg.footer.offset <= 0 { + cfg.footer.offset, err = f.r.Seek(0, io.SeekEnd) + if err != nil { + return nil, fmt.Errorf("arrow/ipc: could retrieve footer offset: %w", err) + } + } + f.footer.offset = cfg.footer.offset + + err = f.readFooter() + if err != nil { + return nil, fmt.Errorf("arrow/ipc: could not decode footer: %w", err) + } + + err = f.readSchema(cfg.ensureNativeEndian) + if err != nil { + return nil, fmt.Errorf("arrow/ipc: could not decode schema: %w", err) + } + + if cfg.schema != nil && !cfg.schema.Equal(f.schema) { + return nil, fmt.Errorf("arrow/ipc: inconsistent schema for reading (got: %v, want: %v)", f.schema, cfg.schema) + } + + return &f, err +} + +func (f *FileReader) readFooter() error { + var err error + + if f.footer.offset <= int64(len(Magic)*2+4) { + return fmt.Errorf("arrow/ipc: file too small (size=%d)", f.footer.offset) + } + + eof := int64(len(Magic) + 4) + buf := make([]byte, eof) + n, err := f.r.ReadAt(buf, f.footer.offset-eof) + if err != nil { + return fmt.Errorf("arrow/ipc: could not read footer: %w", err) + } + if n != len(buf) { + return fmt.Errorf("arrow/ipc: could not read %d bytes from end of file", len(buf)) + } + + if !bytes.Equal(buf[4:], Magic) { + return errNotArrowFile + } + + size := int64(binary.LittleEndian.Uint32(buf[:4])) + if size <= 0 || size+int64(len(Magic)*2+4) > f.footer.offset { + return errInconsistentFileMetadata + } + + buf = make([]byte, size) + n, err = f.r.ReadAt(buf, f.footer.offset-size-eof) + if err != nil { + return fmt.Errorf("arrow/ipc: could not read footer data: %w", err) + } + if n != len(buf) { + return fmt.Errorf("arrow/ipc: could not read %d bytes from footer data", len(buf)) + } + + f.footer.buffer = memory.NewBufferBytes(buf) + f.footer.data = flatbuf.GetRootAsFooter(buf, 0) + return err +} + +func (f *FileReader) readSchema(ensureNativeEndian bool) error { + var ( + err error + kind dictutils.Kind + ) + + schema := f.footer.data.Schema(nil) + if schema == nil { + return fmt.Errorf("arrow/ipc: could not load schema from flatbuffer data") + } + f.schema, err = schemaFromFB(schema, &f.memo) + if err != nil { + return fmt.Errorf("arrow/ipc: could not read schema: %w", err) + } + + if ensureNativeEndian && !f.schema.IsNativeEndian() { + f.swapEndianness = true + f.schema = f.schema.WithEndianness(endian.NativeEndian) + } + + for i := 0; i < f.NumDictionaries(); i++ { + blk, err := f.dict(i) + if err != nil { + return fmt.Errorf("arrow/ipc: could not read dictionary[%d]: %w", i, err) + } + switch { + case !bitutil.IsMultipleOf8(blk.Offset): + return fmt.Errorf("arrow/ipc: invalid file offset=%d for dictionary %d", blk.Offset, i) + case !bitutil.IsMultipleOf8(int64(blk.Meta)): + return fmt.Errorf("arrow/ipc: invalid file metadata=%d position for dictionary %d", blk.Meta, i) + case !bitutil.IsMultipleOf8(blk.Body): + return fmt.Errorf("arrow/ipc: invalid file body=%d position for dictionary %d", blk.Body, i) + } + + msg, err := blk.NewMessage() + if err != nil { + return err + } + + kind, err = readDictionary(&f.memo, msg.meta, bytes.NewReader(msg.body.Bytes()), f.swapEndianness, f.mem) + if err != nil { + return err + } + if kind == dictutils.KindReplacement { + return errors.New("arrow/ipc: unsupported dictionary replacement in IPC file") + } + } + + return err +} + +func (f *FileReader) block(i int) (fileBlock, error) { + var blk flatbuf.Block + if !f.footer.data.RecordBatches(&blk, i) { + return fileBlock{}, fmt.Errorf("arrow/ipc: could not extract file block %d", i) + } + + return fileBlock{ + Offset: blk.Offset(), + Meta: blk.MetaDataLength(), + Body: blk.BodyLength(), + r: f.r, + mem: f.mem, + }, nil +} + +func (f *FileReader) dict(i int) (fileBlock, error) { + var blk flatbuf.Block + if !f.footer.data.Dictionaries(&blk, i) { + return fileBlock{}, fmt.Errorf("arrow/ipc: could not extract dictionary block %d", i) + } + + return fileBlock{ + Offset: blk.Offset(), + Meta: blk.MetaDataLength(), + Body: blk.BodyLength(), + r: f.r, + mem: f.mem, + }, nil +} + +func (f *FileReader) Schema() *arrow.Schema { + return f.schema +} + +func (f *FileReader) NumDictionaries() int { + if f.footer.data == nil { + return 0 + } + return f.footer.data.DictionariesLength() +} + +func (f *FileReader) NumRecords() int { + return f.footer.data.RecordBatchesLength() +} + +func (f *FileReader) Version() MetadataVersion { + return MetadataVersion(f.footer.data.Version()) +} + +// Close cleans up resources used by the File. +// Close does not close the underlying reader. +func (f *FileReader) Close() error { + if f.footer.data != nil { + f.footer.data = nil + } + + if f.footer.buffer != nil { + f.footer.buffer.Release() + f.footer.buffer = nil + } + + if f.record != nil { + f.record.Release() + f.record = nil + } + return nil +} + +// Record returns the i-th record from the file. +// The returned value is valid until the next call to Record. +// Users need to call Retain on that Record to keep it valid for longer. +func (f *FileReader) Record(i int) (arrow.Record, error) { + record, err := f.RecordAt(i) + if err != nil { + return nil, err + } + + if f.record != nil { + f.record.Release() + } + + f.record = record + return record, nil +} + +// Record returns the i-th record from the file. Ownership is transferred to the +// caller and must call Release() to free the memory. This method is safe to +// call concurrently. +func (f *FileReader) RecordAt(i int) (arrow.Record, error) { + if i < 0 || i > f.NumRecords() { + panic("arrow/ipc: record index out of bounds") + } + + blk, err := f.block(i) + if err != nil { + return nil, err + } + switch { + case !bitutil.IsMultipleOf8(blk.Offset): + return nil, fmt.Errorf("arrow/ipc: invalid file offset=%d for record %d", blk.Offset, i) + case !bitutil.IsMultipleOf8(int64(blk.Meta)): + return nil, fmt.Errorf("arrow/ipc: invalid file metadata=%d position for record %d", blk.Meta, i) + case !bitutil.IsMultipleOf8(blk.Body): + return nil, fmt.Errorf("arrow/ipc: invalid file body=%d position for record %d", blk.Body, i) + } + + msg, err := blk.NewMessage() + if err != nil { + return nil, err + } + defer msg.Release() + + if msg.Type() != MessageRecordBatch { + return nil, fmt.Errorf("arrow/ipc: message %d is not a Record", i) + } + + return newRecord(f.schema, &f.memo, msg.meta, bytes.NewReader(msg.body.Bytes()), f.swapEndianness, f.mem), nil +} + +// Read reads the current record from the underlying stream and an error, if any. +// When the Reader reaches the end of the underlying stream, it returns (nil, io.EOF). +// +// The returned record value is valid until the next call to Read. +// Users need to call Retain on that Record to keep it valid for longer. +func (f *FileReader) Read() (rec arrow.Record, err error) { + if f.irec == f.NumRecords() { + return nil, io.EOF + } + rec, f.err = f.Record(f.irec) + f.irec++ + return rec, f.err +} + +// ReadAt reads the i-th record from the underlying stream and an error, if any. +func (f *FileReader) ReadAt(i int64) (arrow.Record, error) { + return f.Record(int(i)) +} + +func newRecord(schema *arrow.Schema, memo *dictutils.Memo, meta *memory.Buffer, body ReadAtSeeker, swapEndianness bool, mem memory.Allocator) arrow.Record { + var ( + msg = flatbuf.GetRootAsMessage(meta.Bytes(), 0) + md flatbuf.RecordBatch + codec decompressor + ) + initFB(&md, msg.Header) + rows := md.Length() + + bodyCompress := md.Compression(nil) + if bodyCompress != nil { + codec = getDecompressor(bodyCompress.Codec()) + defer codec.Close() + } + + ctx := &arrayLoaderContext{ + src: ipcSource{ + meta: &md, + r: body, + codec: codec, + mem: mem, + }, + memo: memo, + max: kMaxNestingDepth, + version: MetadataVersion(msg.Version()), + } + + pos := dictutils.NewFieldPos() + cols := make([]arrow.Array, len(schema.Fields())) + for i, field := range schema.Fields() { + data := ctx.loadArray(field.Type) + defer data.Release() + + if err := dictutils.ResolveFieldDict(memo, data, pos.Child(int32(i)), mem); err != nil { + panic(err) + } + + if swapEndianness { + swapEndianArrayData(data.(*array.Data)) + } + + cols[i] = array.MakeFromData(data) + defer cols[i].Release() + } + + return array.NewRecord(schema, cols, rows) +} + +type ipcSource struct { + meta *flatbuf.RecordBatch + r ReadAtSeeker + codec decompressor + mem memory.Allocator +} + +func (src *ipcSource) buffer(i int) *memory.Buffer { + var buf flatbuf.Buffer + if !src.meta.Buffers(&buf, i) { + panic("arrow/ipc: buffer index out of bound") + } + + if buf.Length() == 0 { + return memory.NewBufferBytes(nil) + } + + raw := memory.NewResizableBuffer(src.mem) + if src.codec == nil { + raw.Resize(int(buf.Length())) + _, err := src.r.ReadAt(raw.Bytes(), buf.Offset()) + if err != nil { + panic(err) + } + } else { + sr := io.NewSectionReader(src.r, buf.Offset(), buf.Length()) + var uncompressedSize uint64 + + err := binary.Read(sr, binary.LittleEndian, &uncompressedSize) + if err != nil { + panic(err) + } + + var r io.Reader = sr + // check for an uncompressed buffer + if int64(uncompressedSize) != -1 { + raw.Resize(int(uncompressedSize)) + src.codec.Reset(sr) + r = src.codec + } else { + raw.Resize(int(buf.Length() - 8)) + } + + if _, err = io.ReadFull(r, raw.Bytes()); err != nil { + panic(err) + } + } + + return raw +} + +func (src *ipcSource) fieldMetadata(i int) *flatbuf.FieldNode { + var node flatbuf.FieldNode + if !src.meta.Nodes(&node, i) { + panic("arrow/ipc: field metadata out of bound") + } + return &node +} + +type arrayLoaderContext struct { + src ipcSource + ifield int + ibuffer int + max int + memo *dictutils.Memo + version MetadataVersion +} + +func (ctx *arrayLoaderContext) field() *flatbuf.FieldNode { + field := ctx.src.fieldMetadata(ctx.ifield) + ctx.ifield++ + return field +} + +func (ctx *arrayLoaderContext) buffer() *memory.Buffer { + buf := ctx.src.buffer(ctx.ibuffer) + ctx.ibuffer++ + return buf +} + +func (ctx *arrayLoaderContext) loadArray(dt arrow.DataType) arrow.ArrayData { + switch dt := dt.(type) { + case *arrow.NullType: + return ctx.loadNull() + + case *arrow.DictionaryType: + indices := ctx.loadPrimitive(dt.IndexType) + defer indices.Release() + return array.NewData(dt, indices.Len(), indices.Buffers(), indices.Children(), indices.NullN(), indices.Offset()) + + case *arrow.BooleanType, + *arrow.Int8Type, *arrow.Int16Type, *arrow.Int32Type, *arrow.Int64Type, + *arrow.Uint8Type, *arrow.Uint16Type, *arrow.Uint32Type, *arrow.Uint64Type, + *arrow.Float16Type, *arrow.Float32Type, *arrow.Float64Type, + *arrow.Decimal128Type, *arrow.Decimal256Type, + *arrow.Time32Type, *arrow.Time64Type, + *arrow.TimestampType, + *arrow.Date32Type, *arrow.Date64Type, + *arrow.MonthIntervalType, *arrow.DayTimeIntervalType, *arrow.MonthDayNanoIntervalType, + *arrow.DurationType: + return ctx.loadPrimitive(dt) + + case *arrow.BinaryType, *arrow.StringType, *arrow.LargeStringType, *arrow.LargeBinaryType: + return ctx.loadBinary(dt) + + case *arrow.FixedSizeBinaryType: + return ctx.loadFixedSizeBinary(dt) + + case *arrow.ListType: + return ctx.loadList(dt) + + case *arrow.LargeListType: + return ctx.loadList(dt) + + case *arrow.ListViewType: + return ctx.loadListView(dt) + + case *arrow.LargeListViewType: + return ctx.loadListView(dt) + + case *arrow.FixedSizeListType: + return ctx.loadFixedSizeList(dt) + + case *arrow.StructType: + return ctx.loadStruct(dt) + + case *arrow.MapType: + return ctx.loadMap(dt) + + case arrow.ExtensionType: + storage := ctx.loadArray(dt.StorageType()) + defer storage.Release() + return array.NewData(dt, storage.Len(), storage.Buffers(), storage.Children(), storage.NullN(), storage.Offset()) + + case *arrow.RunEndEncodedType: + field, buffers := ctx.loadCommon(dt.ID(), 1) + defer releaseBuffers(buffers) + + runEnds := ctx.loadChild(dt.RunEnds()) + defer runEnds.Release() + values := ctx.loadChild(dt.Encoded()) + defer values.Release() + + return array.NewData(dt, int(field.Length()), buffers, []arrow.ArrayData{runEnds, values}, int(field.NullCount()), 0) + + case arrow.UnionType: + return ctx.loadUnion(dt) + + default: + panic(fmt.Errorf("arrow/ipc: array type %T not handled yet", dt)) + } +} + +func (ctx *arrayLoaderContext) loadCommon(typ arrow.Type, nbufs int) (*flatbuf.FieldNode, []*memory.Buffer) { + buffers := make([]*memory.Buffer, 0, nbufs) + field := ctx.field() + + var buf *memory.Buffer + + if internal.HasValidityBitmap(typ, flatbuf.MetadataVersion(ctx.version)) { + switch field.NullCount() { + case 0: + ctx.ibuffer++ + default: + buf = ctx.buffer() + } + } + buffers = append(buffers, buf) + + return field, buffers +} + +func (ctx *arrayLoaderContext) loadChild(dt arrow.DataType) arrow.ArrayData { + if ctx.max == 0 { + panic("arrow/ipc: nested type limit reached") + } + ctx.max-- + sub := ctx.loadArray(dt) + ctx.max++ + return sub +} + +func (ctx *arrayLoaderContext) loadNull() arrow.ArrayData { + field := ctx.field() + return array.NewData(arrow.Null, int(field.Length()), nil, nil, int(field.NullCount()), 0) +} + +func (ctx *arrayLoaderContext) loadPrimitive(dt arrow.DataType) arrow.ArrayData { + field, buffers := ctx.loadCommon(dt.ID(), 2) + + switch field.Length() { + case 0: + buffers = append(buffers, nil) + ctx.ibuffer++ + default: + buffers = append(buffers, ctx.buffer()) + } + + defer releaseBuffers(buffers) + + return array.NewData(dt, int(field.Length()), buffers, nil, int(field.NullCount()), 0) +} + +func (ctx *arrayLoaderContext) loadBinary(dt arrow.DataType) arrow.ArrayData { + field, buffers := ctx.loadCommon(dt.ID(), 3) + buffers = append(buffers, ctx.buffer(), ctx.buffer()) + defer releaseBuffers(buffers) + + return array.NewData(dt, int(field.Length()), buffers, nil, int(field.NullCount()), 0) +} + +func (ctx *arrayLoaderContext) loadFixedSizeBinary(dt *arrow.FixedSizeBinaryType) arrow.ArrayData { + field, buffers := ctx.loadCommon(dt.ID(), 2) + buffers = append(buffers, ctx.buffer()) + defer releaseBuffers(buffers) + + return array.NewData(dt, int(field.Length()), buffers, nil, int(field.NullCount()), 0) +} + +func (ctx *arrayLoaderContext) loadMap(dt *arrow.MapType) arrow.ArrayData { + field, buffers := ctx.loadCommon(dt.ID(), 2) + buffers = append(buffers, ctx.buffer()) + defer releaseBuffers(buffers) + + sub := ctx.loadChild(dt.Elem()) + defer sub.Release() + + return array.NewData(dt, int(field.Length()), buffers, []arrow.ArrayData{sub}, int(field.NullCount()), 0) +} + +func (ctx *arrayLoaderContext) loadList(dt arrow.ListLikeType) arrow.ArrayData { + field, buffers := ctx.loadCommon(dt.ID(), 2) + buffers = append(buffers, ctx.buffer()) + defer releaseBuffers(buffers) + + sub := ctx.loadChild(dt.Elem()) + defer sub.Release() + + return array.NewData(dt, int(field.Length()), buffers, []arrow.ArrayData{sub}, int(field.NullCount()), 0) +} + +func (ctx *arrayLoaderContext) loadListView(dt arrow.VarLenListLikeType) arrow.ArrayData { + field, buffers := ctx.loadCommon(dt.ID(), 3) + buffers = append(buffers, ctx.buffer(), ctx.buffer()) + defer releaseBuffers(buffers) + + sub := ctx.loadChild(dt.Elem()) + defer sub.Release() + + return array.NewData(dt, int(field.Length()), buffers, []arrow.ArrayData{sub}, int(field.NullCount()), 0) +} + +func (ctx *arrayLoaderContext) loadFixedSizeList(dt *arrow.FixedSizeListType) arrow.ArrayData { + field, buffers := ctx.loadCommon(dt.ID(), 1) + defer releaseBuffers(buffers) + + sub := ctx.loadChild(dt.Elem()) + defer sub.Release() + + return array.NewData(dt, int(field.Length()), buffers, []arrow.ArrayData{sub}, int(field.NullCount()), 0) +} + +func (ctx *arrayLoaderContext) loadStruct(dt *arrow.StructType) arrow.ArrayData { + field, buffers := ctx.loadCommon(dt.ID(), 1) + defer releaseBuffers(buffers) + + subs := make([]arrow.ArrayData, len(dt.Fields())) + for i, f := range dt.Fields() { + subs[i] = ctx.loadChild(f.Type) + } + defer func() { + for i := range subs { + subs[i].Release() + } + }() + + return array.NewData(dt, int(field.Length()), buffers, subs, int(field.NullCount()), 0) +} + +func (ctx *arrayLoaderContext) loadUnion(dt arrow.UnionType) arrow.ArrayData { + // Sparse unions have 2 buffers (a nil validity bitmap, and the type ids) + nBuffers := 2 + // Dense unions have a third buffer, the offsets + if dt.Mode() == arrow.DenseMode { + nBuffers = 3 + } + + field, buffers := ctx.loadCommon(dt.ID(), nBuffers) + if field.NullCount() != 0 && buffers[0] != nil { + panic("arrow/ipc: cannot read pre-1.0.0 union array with top-level validity bitmap") + } + + switch field.Length() { + case 0: + buffers = append(buffers, memory.NewBufferBytes([]byte{})) + ctx.ibuffer++ + if dt.Mode() == arrow.DenseMode { + buffers = append(buffers, nil) + ctx.ibuffer++ + } + default: + buffers = append(buffers, ctx.buffer()) + if dt.Mode() == arrow.DenseMode { + buffers = append(buffers, ctx.buffer()) + } + } + + defer releaseBuffers(buffers) + subs := make([]arrow.ArrayData, len(dt.Fields())) + for i, f := range dt.Fields() { + subs[i] = ctx.loadChild(f.Type) + } + defer func() { + for i := range subs { + subs[i].Release() + } + }() + return array.NewData(dt, int(field.Length()), buffers, subs, 0, 0) +} + +func readDictionary(memo *dictutils.Memo, meta *memory.Buffer, body ReadAtSeeker, swapEndianness bool, mem memory.Allocator) (dictutils.Kind, error) { + var ( + msg = flatbuf.GetRootAsMessage(meta.Bytes(), 0) + md flatbuf.DictionaryBatch + data flatbuf.RecordBatch + codec decompressor + ) + initFB(&md, msg.Header) + + md.Data(&data) + bodyCompress := data.Compression(nil) + if bodyCompress != nil { + codec = getDecompressor(bodyCompress.Codec()) + } + + id := md.Id() + // look up the dictionary value type, which must have been added to the + // memo already before calling this function + valueType, ok := memo.Type(id) + if !ok { + return 0, fmt.Errorf("arrow/ipc: no dictionary type found with id: %d", id) + } + + ctx := &arrayLoaderContext{ + src: ipcSource{ + meta: &data, + codec: codec, + r: body, + mem: mem, + }, + memo: memo, + max: kMaxNestingDepth, + } + + dict := ctx.loadArray(valueType) + defer dict.Release() + + if swapEndianness { + swapEndianArrayData(dict.(*array.Data)) + } + + if md.IsDelta() { + memo.AddDelta(id, dict) + return dictutils.KindDelta, nil + } + if memo.AddOrReplace(id, dict) { + return dictutils.KindNew, nil + } + return dictutils.KindReplacement, nil +} + +func releaseBuffers(buffers []*memory.Buffer) { + for _, b := range buffers { + if b != nil { + b.Release() + } + } +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/ipc/file_writer.go b/vendor/github.com/apache/arrow/go/v14/arrow/ipc/file_writer.go new file mode 100644 index 000000000..12384225b --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/ipc/file_writer.go @@ -0,0 +1,394 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ipc + +import ( + "encoding/binary" + "fmt" + "io" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/bitutil" + "github.com/apache/arrow/go/v14/arrow/internal/dictutils" + "github.com/apache/arrow/go/v14/arrow/internal/flatbuf" + "github.com/apache/arrow/go/v14/arrow/memory" +) + +// PayloadWriter is an interface for injecting a different payloadwriter +// allowing more reusability with the Writer object with other scenarios, +// such as with Flight data +type PayloadWriter interface { + Start() error + WritePayload(Payload) error + Close() error +} + +type pwriter struct { + w io.WriteSeeker + pos int64 + + schema *arrow.Schema + dicts []fileBlock + recs []fileBlock +} + +func (w *pwriter) Start() error { + var err error + + err = w.updatePos() + if err != nil { + return fmt.Errorf("arrow/ipc: could not update position while in start: %w", err) + } + + // only necessary to align to 8-byte boundary at the start of the file + _, err = w.Write(Magic) + if err != nil { + return fmt.Errorf("arrow/ipc: could not write magic Arrow bytes: %w", err) + } + + err = w.align(kArrowIPCAlignment) + if err != nil { + return fmt.Errorf("arrow/ipc: could not align start block: %w", err) + } + + return err +} + +func (w *pwriter) WritePayload(p Payload) error { + blk := fileBlock{Offset: w.pos, Meta: 0, Body: p.size} + n, err := writeIPCPayload(w, p) + if err != nil { + return err + } + + blk.Meta = int32(n) + + err = w.updatePos() + if err != nil { + return fmt.Errorf("arrow/ipc: could not update position while in write-payload: %w", err) + } + + switch flatbuf.MessageHeader(p.msg) { + case flatbuf.MessageHeaderDictionaryBatch: + w.dicts = append(w.dicts, blk) + case flatbuf.MessageHeaderRecordBatch: + w.recs = append(w.recs, blk) + } + + return nil +} + +func (w *pwriter) Close() error { + var err error + + // write file footer + err = w.updatePos() + if err != nil { + return fmt.Errorf("arrow/ipc: could not update position while in close: %w", err) + } + + pos := w.pos + err = writeFileFooter(w.schema, w.dicts, w.recs, w) + if err != nil { + return fmt.Errorf("arrow/ipc: could not write file footer: %w", err) + } + + // write file footer length + err = w.updatePos() // not strictly needed as we passed w to writeFileFooter... + if err != nil { + return fmt.Errorf("arrow/ipc: could not compute file footer length: %w", err) + } + + size := w.pos - pos + if size <= 0 { + return fmt.Errorf("arrow/ipc: invalid file footer size (size=%d)", size) + } + + buf := make([]byte, 4) + binary.LittleEndian.PutUint32(buf, uint32(size)) + _, err = w.Write(buf) + if err != nil { + return fmt.Errorf("arrow/ipc: could not write file footer size: %w", err) + } + + _, err = w.Write(Magic) + if err != nil { + return fmt.Errorf("arrow/ipc: could not write Arrow magic bytes: %w", err) + } + + return nil +} + +func (w *pwriter) updatePos() error { + var err error + w.pos, err = w.w.Seek(0, io.SeekCurrent) + return err +} + +func (w *pwriter) align(align int32) error { + remainder := paddedLength(w.pos, align) - w.pos + if remainder == 0 { + return nil + } + + _, err := w.Write(paddingBytes[:int(remainder)]) + return err +} + +func (w *pwriter) Write(p []byte) (int, error) { + n, err := w.w.Write(p) + w.pos += int64(n) + return n, err +} + +func writeIPCPayload(w io.Writer, p Payload) (int, error) { + n, err := writeMessage(p.meta, kArrowIPCAlignment, w) + if err != nil { + return n, err + } + + // now write the buffers + for _, buf := range p.body { + var ( + size int64 + padding int64 + ) + + // the buffer might be null if we are handling zero row lengths. + if buf != nil { + size = int64(buf.Len()) + padding = bitutil.CeilByte64(size) - size + } + + if size > 0 { + _, err = w.Write(buf.Bytes()) + if err != nil { + return n, fmt.Errorf("arrow/ipc: could not write payload message body: %w", err) + } + } + + if padding > 0 { + _, err = w.Write(paddingBytes[:padding]) + if err != nil { + return n, fmt.Errorf("arrow/ipc: could not write payload message padding: %w", err) + } + } + } + + return n, err +} + +// Payload is the underlying message object which is passed to the payload writer +// for actually writing out ipc messages +type Payload struct { + msg MessageType + meta *memory.Buffer + body []*memory.Buffer + size int64 // length of body +} + +// Meta returns the buffer containing the metadata for this payload, +// callers must call Release on the buffer +func (p *Payload) Meta() *memory.Buffer { + if p.meta != nil { + p.meta.Retain() + } + return p.meta +} + +// SerializeBody serializes the body buffers and writes them to the provided +// writer. +func (p *Payload) SerializeBody(w io.Writer) error { + for _, data := range p.body { + if data == nil { + continue + } + + size := int64(data.Len()) + padding := bitutil.CeilByte64(size) - size + if size > 0 { + if _, err := w.Write(data.Bytes()); err != nil { + return fmt.Errorf("arrow/ipc: could not write payload message body: %w", err) + } + + if padding > 0 { + if _, err := w.Write(paddingBytes[:padding]); err != nil { + return fmt.Errorf("arrow/ipc: could not write payload message padding bytes: %w", err) + } + } + } + } + return nil +} + +func (p *Payload) Release() { + if p.meta != nil { + p.meta.Release() + p.meta = nil + } + for i, b := range p.body { + if b == nil { + continue + } + b.Release() + p.body[i] = nil + } +} + +type payloads []Payload + +func (ps payloads) Release() { + for i := range ps { + ps[i].Release() + } +} + +// FileWriter is an Arrow file writer. +type FileWriter struct { + w io.WriteSeeker + + mem memory.Allocator + + header struct { + started bool + offset int64 + } + + footer struct { + written bool + } + + pw PayloadWriter + + schema *arrow.Schema + mapper dictutils.Mapper + codec flatbuf.CompressionType + compressNP int + minSpaceSavings *float64 + + // map of the last written dictionaries by id + // so we can avoid writing the same dictionary over and over + // also needed for correctness when writing IPC format which + // does not allow replacements or deltas. + lastWrittenDicts map[int64]arrow.Array +} + +// NewFileWriter opens an Arrow file using the provided writer w. +func NewFileWriter(w io.WriteSeeker, opts ...Option) (*FileWriter, error) { + var ( + cfg = newConfig(opts...) + err error + ) + + f := FileWriter{ + w: w, + pw: &pwriter{w: w, schema: cfg.schema, pos: -1}, + mem: cfg.alloc, + schema: cfg.schema, + codec: cfg.codec, + compressNP: cfg.compressNP, + minSpaceSavings: cfg.minSpaceSavings, + } + + pos, err := f.w.Seek(0, io.SeekCurrent) + if err != nil { + return nil, fmt.Errorf("arrow/ipc: could not seek current position: %w", err) + } + f.header.offset = pos + + return &f, err +} + +func (f *FileWriter) Close() error { + err := f.checkStarted() + if err != nil { + return fmt.Errorf("arrow/ipc: could not write empty file: %w", err) + } + + if f.footer.written { + return nil + } + + err = f.pw.Close() + if err != nil { + return fmt.Errorf("arrow/ipc: could not close payload writer: %w", err) + } + f.footer.written = true + + return nil +} + +func (f *FileWriter) Write(rec arrow.Record) error { + schema := rec.Schema() + if schema == nil || !schema.Equal(f.schema) { + return errInconsistentSchema + } + + if err := f.checkStarted(); err != nil { + return fmt.Errorf("arrow/ipc: could not write header: %w", err) + } + + const allow64b = true + var ( + data = Payload{msg: MessageRecordBatch} + enc = newRecordEncoder(f.mem, 0, kMaxNestingDepth, allow64b, f.codec, f.compressNP, f.minSpaceSavings) + ) + defer data.Release() + + err := writeDictionaryPayloads(f.mem, rec, true, false, &f.mapper, f.lastWrittenDicts, f.pw, enc) + if err != nil { + return fmt.Errorf("arrow/ipc: failure writing dictionary batches: %w", err) + } + + enc.reset() + if err := enc.Encode(&data, rec); err != nil { + return fmt.Errorf("arrow/ipc: could not encode record to payload: %w", err) + } + + return f.pw.WritePayload(data) +} + +func (f *FileWriter) checkStarted() error { + if !f.header.started { + return f.start() + } + return nil +} + +func (f *FileWriter) start() error { + f.header.started = true + err := f.pw.Start() + if err != nil { + return err + } + + f.mapper.ImportSchema(f.schema) + f.lastWrittenDicts = make(map[int64]arrow.Array) + + // write out schema payloads + ps := payloadFromSchema(f.schema, f.mem, &f.mapper) + defer ps.Release() + + for _, data := range ps { + err = f.pw.WritePayload(data) + if err != nil { + return err + } + } + + return nil +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/ipc/ipc.go b/vendor/github.com/apache/arrow/go/v14/arrow/ipc/ipc.go new file mode 100644 index 000000000..6c04b6f5a --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/ipc/ipc.go @@ -0,0 +1,199 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ipc + +import ( + "io" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/arrio" + "github.com/apache/arrow/go/v14/arrow/internal/flatbuf" + "github.com/apache/arrow/go/v14/arrow/memory" +) + +const ( + errNotArrowFile = errString("arrow/ipc: not an Arrow file") + errInconsistentFileMetadata = errString("arrow/ipc: file is smaller than indicated metadata size") + errInconsistentSchema = errString("arrow/ipc: tried to write record batch with different schema") + errMaxRecursion = errString("arrow/ipc: max recursion depth reached") + errBigArray = errString("arrow/ipc: array larger than 2^31-1 in length") + + kArrowAlignment = 64 // buffers are padded to 64b boundaries (for SIMD) + kTensorAlignment = 64 // tensors are padded to 64b boundaries + kArrowIPCAlignment = 8 // align on 8b boundaries in IPC +) + +var ( + paddingBytes [kArrowAlignment]byte + kEOS = [8]byte{0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0} // end of stream message + kIPCContToken uint32 = 0xFFFFFFFF // 32b continuation indicator for FlatBuffers 8b alignment +) + +func paddedLength(nbytes int64, alignment int32) int64 { + align := int64(alignment) + return ((nbytes + align - 1) / align) * align +} + +type errString string + +func (s errString) Error() string { + return string(s) +} + +type ReadAtSeeker interface { + io.Reader + io.Seeker + io.ReaderAt +} + +type config struct { + alloc memory.Allocator + schema *arrow.Schema + footer struct { + offset int64 + } + codec flatbuf.CompressionType + compressNP int + ensureNativeEndian bool + noAutoSchema bool + emitDictDeltas bool + minSpaceSavings *float64 +} + +func newConfig(opts ...Option) *config { + cfg := &config{ + alloc: memory.NewGoAllocator(), + codec: -1, // uncompressed + ensureNativeEndian: true, + } + + for _, opt := range opts { + opt(cfg) + } + + return cfg +} + +// Option is a functional option to configure opening or creating Arrow files +// and streams. +type Option func(*config) + +// WithFooterOffset specifies the Arrow footer position in bytes. +func WithFooterOffset(offset int64) Option { + return func(cfg *config) { + cfg.footer.offset = offset + } +} + +// WithAllocator specifies the Arrow memory allocator used while building records. +func WithAllocator(mem memory.Allocator) Option { + return func(cfg *config) { + cfg.alloc = mem + } +} + +// WithSchema specifies the Arrow schema to be used for reading or writing. +func WithSchema(schema *arrow.Schema) Option { + return func(cfg *config) { + cfg.schema = schema + } +} + +// WithLZ4 tells the writer to use LZ4 Frame compression on the data +// buffers before writing. Requires >= Arrow 1.0.0 to read/decompress +func WithLZ4() Option { + return func(cfg *config) { + cfg.codec = flatbuf.CompressionTypeLZ4_FRAME + } +} + +// WithZstd tells the writer to use ZSTD compression on the data +// buffers before writing. Requires >= Arrow 1.0.0 to read/decompress +func WithZstd() Option { + return func(cfg *config) { + cfg.codec = flatbuf.CompressionTypeZSTD + } +} + +// WithCompressConcurrency specifies a number of goroutines to spin up for +// concurrent compression of the body buffers when writing compress IPC records. +// If n <= 1 then compression will be done serially without goroutine +// parallelization. Default is 0. +func WithCompressConcurrency(n int) Option { + return func(cfg *config) { + cfg.compressNP = n + } +} + +// WithEnsureNativeEndian specifies whether or not to automatically byte-swap +// buffers with endian-sensitive data if the schema's endianness is not the +// platform-native endianness. This includes all numeric types, temporal types, +// decimal types, as well as the offset buffers of variable-sized binary and +// list-like types. +// +// This is only relevant to ipc Reader objects, not to writers. This defaults +// to true. +func WithEnsureNativeEndian(v bool) Option { + return func(cfg *config) { + cfg.ensureNativeEndian = v + } +} + +// WithDelayedReadSchema alters the ipc.Reader behavior to delay attempting +// to read the schema from the stream until the first call to Next instead +// of immediately attempting to read a schema from the stream when created. +func WithDelayReadSchema(v bool) Option { + return func(cfg *config) { + cfg.noAutoSchema = v + } +} + +// WithDictionaryDeltas specifies whether or not to emit dictionary deltas. +func WithDictionaryDeltas(v bool) Option { + return func(cfg *config) { + cfg.emitDictDeltas = v + } +} + +// WithMinSpaceSavings specifies a percentage of space savings for +// compression to be applied to buffers. +// +// Space savings is calculated as (1.0 - compressedSize / uncompressedSize). +// +// For example, if minSpaceSavings = 0.1, a 100-byte body buffer won't +// undergo compression if its expected compressed size exceeds 90 bytes. +// If this option is unset, compression will be used indiscriminately. If +// no codec was supplied, this option is ignored. +// +// Values outside of the range [0,1] are handled as errors. +// +// Note that enabling this option may result in unreadable data for Arrow +// Go and C++ versions prior to 12.0.0. +func WithMinSpaceSavings(savings float64) Option { + return func(cfg *config) { + cfg.minSpaceSavings = &savings + } +} + +var ( + _ arrio.Reader = (*Reader)(nil) + _ arrio.Writer = (*Writer)(nil) + _ arrio.Reader = (*FileReader)(nil) + _ arrio.Writer = (*FileWriter)(nil) + + _ arrio.ReaderAt = (*FileReader)(nil) +) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/ipc/message.go b/vendor/github.com/apache/arrow/go/v14/arrow/ipc/message.go new file mode 100644 index 000000000..c5d0ec68d --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/ipc/message.go @@ -0,0 +1,242 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ipc + +import ( + "encoding/binary" + "fmt" + "io" + "sync/atomic" + + "github.com/apache/arrow/go/v14/arrow/internal/debug" + "github.com/apache/arrow/go/v14/arrow/internal/flatbuf" + "github.com/apache/arrow/go/v14/arrow/memory" +) + +// MetadataVersion represents the Arrow metadata version. +type MetadataVersion flatbuf.MetadataVersion + +const ( + MetadataV1 = MetadataVersion(flatbuf.MetadataVersionV1) // version for Arrow-0.1.0 + MetadataV2 = MetadataVersion(flatbuf.MetadataVersionV2) // version for Arrow-0.2.0 + MetadataV3 = MetadataVersion(flatbuf.MetadataVersionV3) // version for Arrow-0.3.0 to 0.7.1 + MetadataV4 = MetadataVersion(flatbuf.MetadataVersionV4) // version for >= Arrow-0.8.0 + MetadataV5 = MetadataVersion(flatbuf.MetadataVersionV5) // version for >= Arrow-1.0.0, backward compatible with v4 +) + +func (m MetadataVersion) String() string { + if v, ok := flatbuf.EnumNamesMetadataVersion[flatbuf.MetadataVersion(m)]; ok { + return v + } + return fmt.Sprintf("MetadataVersion(%d)", int16(m)) +} + +// MessageType represents the type of Message in an Arrow format. +type MessageType flatbuf.MessageHeader + +const ( + MessageNone = MessageType(flatbuf.MessageHeaderNONE) + MessageSchema = MessageType(flatbuf.MessageHeaderSchema) + MessageDictionaryBatch = MessageType(flatbuf.MessageHeaderDictionaryBatch) + MessageRecordBatch = MessageType(flatbuf.MessageHeaderRecordBatch) + MessageTensor = MessageType(flatbuf.MessageHeaderTensor) + MessageSparseTensor = MessageType(flatbuf.MessageHeaderSparseTensor) +) + +func (m MessageType) String() string { + if v, ok := flatbuf.EnumNamesMessageHeader[flatbuf.MessageHeader(m)]; ok { + return v + } + return fmt.Sprintf("MessageType(%d)", int(m)) +} + +// Message is an IPC message, including metadata and body. +type Message struct { + refCount int64 + msg *flatbuf.Message + meta *memory.Buffer + body *memory.Buffer +} + +// NewMessage creates a new message from the metadata and body buffers. +// NewMessage panics if any of these buffers is nil. +func NewMessage(meta, body *memory.Buffer) *Message { + if meta == nil || body == nil { + panic("arrow/ipc: nil buffers") + } + meta.Retain() + body.Retain() + return &Message{ + refCount: 1, + msg: flatbuf.GetRootAsMessage(meta.Bytes(), 0), + meta: meta, + body: body, + } +} + +func newMessageFromFB(meta *flatbuf.Message, body *memory.Buffer) *Message { + if meta == nil || body == nil { + panic("arrow/ipc: nil buffers") + } + body.Retain() + return &Message{ + refCount: 1, + msg: meta, + meta: memory.NewBufferBytes(meta.Table().Bytes), + body: body, + } +} + +// Retain increases the reference count by 1. +// Retain may be called simultaneously from multiple goroutines. +func (msg *Message) Retain() { + atomic.AddInt64(&msg.refCount, 1) +} + +// Release decreases the reference count by 1. +// Release may be called simultaneously from multiple goroutines. +// When the reference count goes to zero, the memory is freed. +func (msg *Message) Release() { + debug.Assert(atomic.LoadInt64(&msg.refCount) > 0, "too many releases") + + if atomic.AddInt64(&msg.refCount, -1) == 0 { + msg.meta.Release() + msg.body.Release() + msg.msg = nil + msg.meta = nil + msg.body = nil + } +} + +func (msg *Message) Version() MetadataVersion { + return MetadataVersion(msg.msg.Version()) +} + +func (msg *Message) Type() MessageType { + return MessageType(msg.msg.HeaderType()) +} + +func (msg *Message) BodyLen() int64 { + return msg.msg.BodyLength() +} + +type MessageReader interface { + Message() (*Message, error) + Release() + Retain() +} + +// MessageReader reads messages from an io.Reader. +type messageReader struct { + r io.Reader + + refCount int64 + msg *Message + + mem memory.Allocator +} + +// NewMessageReader returns a reader that reads messages from an input stream. +func NewMessageReader(r io.Reader, opts ...Option) MessageReader { + cfg := newConfig() + for _, opt := range opts { + opt(cfg) + } + + return &messageReader{r: r, refCount: 1, mem: cfg.alloc} +} + +// Retain increases the reference count by 1. +// Retain may be called simultaneously from multiple goroutines. +func (r *messageReader) Retain() { + atomic.AddInt64(&r.refCount, 1) +} + +// Release decreases the reference count by 1. +// When the reference count goes to zero, the memory is freed. +// Release may be called simultaneously from multiple goroutines. +func (r *messageReader) Release() { + debug.Assert(atomic.LoadInt64(&r.refCount) > 0, "too many releases") + + if atomic.AddInt64(&r.refCount, -1) == 0 { + if r.msg != nil { + r.msg.Release() + r.msg = nil + } + } +} + +// Message returns the current message that has been extracted from the +// underlying stream. +// It is valid until the next call to Message. +func (r *messageReader) Message() (*Message, error) { + var buf = make([]byte, 4) + _, err := io.ReadFull(r.r, buf) + if err != nil { + return nil, fmt.Errorf("arrow/ipc: could not read continuation indicator: %w", err) + } + var ( + cid = binary.LittleEndian.Uint32(buf) + msgLen int32 + ) + switch cid { + case 0: + // EOS message. + return nil, io.EOF // FIXME(sbinet): send nil instead? or a special EOS error? + case kIPCContToken: + _, err = io.ReadFull(r.r, buf) + if err != nil { + return nil, fmt.Errorf("arrow/ipc: could not read message length: %w", err) + } + msgLen = int32(binary.LittleEndian.Uint32(buf)) + if msgLen == 0 { + // optional 0 EOS control message + return nil, io.EOF // FIXME(sbinet): send nil instead? or a special EOS error? + } + + default: + // ARROW-6314: backwards compatibility for reading old IPC + // messages produced prior to version 0.15.0 + msgLen = int32(cid) + } + + buf = make([]byte, msgLen) + _, err = io.ReadFull(r.r, buf) + if err != nil { + return nil, fmt.Errorf("arrow/ipc: could not read message metadata: %w", err) + } + + meta := flatbuf.GetRootAsMessage(buf, 0) + bodyLen := meta.BodyLength() + + body := memory.NewResizableBuffer(r.mem) + defer body.Release() + body.Resize(int(bodyLen)) + + _, err = io.ReadFull(r.r, body.Bytes()) + if err != nil { + return nil, fmt.Errorf("arrow/ipc: could not read message body: %w", err) + } + + if r.msg != nil { + r.msg.Release() + r.msg = nil + } + r.msg = newMessageFromFB(meta, body) + + return r.msg, nil +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/ipc/metadata.go b/vendor/github.com/apache/arrow/go/v14/arrow/ipc/metadata.go new file mode 100644 index 000000000..9bab47d6f --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/ipc/metadata.go @@ -0,0 +1,1287 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ipc + +import ( + "encoding/binary" + "errors" + "fmt" + "io" + "sort" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/endian" + "github.com/apache/arrow/go/v14/arrow/internal/dictutils" + "github.com/apache/arrow/go/v14/arrow/internal/flatbuf" + "github.com/apache/arrow/go/v14/arrow/memory" + flatbuffers "github.com/google/flatbuffers/go" +) + +// Magic string identifying an Apache Arrow file. +var Magic = []byte("ARROW1") + +const ( + currentMetadataVersion = MetadataV5 + minMetadataVersion = MetadataV4 + + // constants for the extension type metadata keys for the type name and + // any extension metadata to be passed to deserialize. + ExtensionTypeKeyName = "ARROW:extension:name" + ExtensionMetadataKeyName = "ARROW:extension:metadata" + + // ARROW-109: We set this number arbitrarily to help catch user mistakes. For + // deeply nested schemas, it is expected the user will indicate explicitly the + // maximum allowed recursion depth + kMaxNestingDepth = 64 +) + +type startVecFunc func(b *flatbuffers.Builder, n int) flatbuffers.UOffsetT + +type fieldMetadata struct { + Len int64 + Nulls int64 + Offset int64 +} + +type bufferMetadata struct { + Offset int64 // relative offset into the memory page to the starting byte of the buffer + Len int64 // absolute length in bytes of the buffer +} + +type fileBlock struct { + Offset int64 + Meta int32 + Body int64 + + r io.ReaderAt + mem memory.Allocator +} + +func fileBlocksToFB(b *flatbuffers.Builder, blocks []fileBlock, start startVecFunc) flatbuffers.UOffsetT { + start(b, len(blocks)) + for i := len(blocks) - 1; i >= 0; i-- { + blk := blocks[i] + flatbuf.CreateBlock(b, blk.Offset, blk.Meta, blk.Body) + } + + return b.EndVector(len(blocks)) +} + +func (blk fileBlock) NewMessage() (*Message, error) { + var ( + err error + buf []byte + body *memory.Buffer + meta *memory.Buffer + r = blk.section() + ) + + meta = memory.NewResizableBuffer(blk.mem) + meta.Resize(int(blk.Meta)) + defer meta.Release() + + buf = meta.Bytes() + _, err = io.ReadFull(r, buf) + if err != nil { + return nil, fmt.Errorf("arrow/ipc: could not read message metadata: %w", err) + } + + prefix := 0 + switch binary.LittleEndian.Uint32(buf) { + case 0: + case kIPCContToken: + prefix = 8 + default: + // ARROW-6314: backwards compatibility for reading old IPC + // messages produced prior to version 0.15.0 + prefix = 4 + } + + // drop buf-size already known from blk.Meta + meta = memory.SliceBuffer(meta, prefix, int(blk.Meta)-prefix) + defer meta.Release() + + body = memory.NewResizableBuffer(blk.mem) + defer body.Release() + body.Resize(int(blk.Body)) + buf = body.Bytes() + _, err = io.ReadFull(r, buf) + if err != nil { + return nil, fmt.Errorf("arrow/ipc: could not read message body: %w", err) + } + + return NewMessage(meta, body), nil +} + +func (blk fileBlock) section() io.Reader { + return io.NewSectionReader(blk.r, blk.Offset, int64(blk.Meta)+blk.Body) +} + +func unitFromFB(unit flatbuf.TimeUnit) arrow.TimeUnit { + switch unit { + case flatbuf.TimeUnitSECOND: + return arrow.Second + case flatbuf.TimeUnitMILLISECOND: + return arrow.Millisecond + case flatbuf.TimeUnitMICROSECOND: + return arrow.Microsecond + case flatbuf.TimeUnitNANOSECOND: + return arrow.Nanosecond + default: + panic(fmt.Errorf("arrow/ipc: invalid flatbuf.TimeUnit(%d) value", unit)) + } +} + +func unitToFB(unit arrow.TimeUnit) flatbuf.TimeUnit { + switch unit { + case arrow.Second: + return flatbuf.TimeUnitSECOND + case arrow.Millisecond: + return flatbuf.TimeUnitMILLISECOND + case arrow.Microsecond: + return flatbuf.TimeUnitMICROSECOND + case arrow.Nanosecond: + return flatbuf.TimeUnitNANOSECOND + default: + panic(fmt.Errorf("arrow/ipc: invalid arrow.TimeUnit(%d) value", unit)) + } +} + +// initFB is a helper function to handle flatbuffers' polymorphism. +func initFB(t interface { + Table() flatbuffers.Table + Init([]byte, flatbuffers.UOffsetT) +}, f func(tbl *flatbuffers.Table) bool) { + tbl := t.Table() + if !f(&tbl) { + panic(fmt.Errorf("arrow/ipc: could not initialize %T from flatbuffer", t)) + } + t.Init(tbl.Bytes, tbl.Pos) +} + +func fieldFromFB(field *flatbuf.Field, pos dictutils.FieldPos, memo *dictutils.Memo) (arrow.Field, error) { + var ( + err error + o arrow.Field + ) + + o.Name = string(field.Name()) + o.Nullable = field.Nullable() + o.Metadata, err = metadataFromFB(field) + if err != nil { + return o, err + } + + n := field.ChildrenLength() + children := make([]arrow.Field, n) + for i := range children { + var childFB flatbuf.Field + if !field.Children(&childFB, i) { + return o, fmt.Errorf("arrow/ipc: could not load field child %d", i) + + } + child, err := fieldFromFB(&childFB, pos.Child(int32(i)), memo) + if err != nil { + return o, fmt.Errorf("arrow/ipc: could not convert field child %d: %w", i, err) + } + children[i] = child + } + + o.Type, err = typeFromFB(field, pos, children, &o.Metadata, memo) + if err != nil { + return o, fmt.Errorf("arrow/ipc: could not convert field type: %w", err) + } + + return o, nil +} + +func fieldToFB(b *flatbuffers.Builder, pos dictutils.FieldPos, field arrow.Field, memo *dictutils.Mapper) flatbuffers.UOffsetT { + var visitor = fieldVisitor{b: b, memo: memo, pos: pos, meta: make(map[string]string)} + return visitor.result(field) +} + +type fieldVisitor struct { + b *flatbuffers.Builder + memo *dictutils.Mapper + pos dictutils.FieldPos + dtype flatbuf.Type + offset flatbuffers.UOffsetT + kids []flatbuffers.UOffsetT + meta map[string]string +} + +func (fv *fieldVisitor) visit(field arrow.Field) { + dt := field.Type + switch dt := dt.(type) { + case *arrow.NullType: + fv.dtype = flatbuf.TypeNull + flatbuf.NullStart(fv.b) + fv.offset = flatbuf.NullEnd(fv.b) + + case *arrow.BooleanType: + fv.dtype = flatbuf.TypeBool + flatbuf.BoolStart(fv.b) + fv.offset = flatbuf.BoolEnd(fv.b) + + case *arrow.Uint8Type: + fv.dtype = flatbuf.TypeInt + fv.offset = intToFB(fv.b, int32(dt.BitWidth()), false) + + case *arrow.Uint16Type: + fv.dtype = flatbuf.TypeInt + fv.offset = intToFB(fv.b, int32(dt.BitWidth()), false) + + case *arrow.Uint32Type: + fv.dtype = flatbuf.TypeInt + fv.offset = intToFB(fv.b, int32(dt.BitWidth()), false) + + case *arrow.Uint64Type: + fv.dtype = flatbuf.TypeInt + fv.offset = intToFB(fv.b, int32(dt.BitWidth()), false) + + case *arrow.Int8Type: + fv.dtype = flatbuf.TypeInt + fv.offset = intToFB(fv.b, int32(dt.BitWidth()), true) + + case *arrow.Int16Type: + fv.dtype = flatbuf.TypeInt + fv.offset = intToFB(fv.b, int32(dt.BitWidth()), true) + + case *arrow.Int32Type: + fv.dtype = flatbuf.TypeInt + fv.offset = intToFB(fv.b, int32(dt.BitWidth()), true) + + case *arrow.Int64Type: + fv.dtype = flatbuf.TypeInt + fv.offset = intToFB(fv.b, int32(dt.BitWidth()), true) + + case *arrow.Float16Type: + fv.dtype = flatbuf.TypeFloatingPoint + fv.offset = floatToFB(fv.b, int32(dt.BitWidth())) + + case *arrow.Float32Type: + fv.dtype = flatbuf.TypeFloatingPoint + fv.offset = floatToFB(fv.b, int32(dt.BitWidth())) + + case *arrow.Float64Type: + fv.dtype = flatbuf.TypeFloatingPoint + fv.offset = floatToFB(fv.b, int32(dt.BitWidth())) + + case *arrow.Decimal128Type: + fv.dtype = flatbuf.TypeDecimal + flatbuf.DecimalStart(fv.b) + flatbuf.DecimalAddPrecision(fv.b, dt.Precision) + flatbuf.DecimalAddScale(fv.b, dt.Scale) + flatbuf.DecimalAddBitWidth(fv.b, 128) + fv.offset = flatbuf.DecimalEnd(fv.b) + + case *arrow.Decimal256Type: + fv.dtype = flatbuf.TypeDecimal + flatbuf.DecimalStart(fv.b) + flatbuf.DecimalAddPrecision(fv.b, dt.Precision) + flatbuf.DecimalAddScale(fv.b, dt.Scale) + flatbuf.DecimalAddBitWidth(fv.b, 256) + fv.offset = flatbuf.DecimalEnd(fv.b) + + case *arrow.FixedSizeBinaryType: + fv.dtype = flatbuf.TypeFixedSizeBinary + flatbuf.FixedSizeBinaryStart(fv.b) + flatbuf.FixedSizeBinaryAddByteWidth(fv.b, int32(dt.ByteWidth)) + fv.offset = flatbuf.FixedSizeBinaryEnd(fv.b) + + case *arrow.BinaryType: + fv.dtype = flatbuf.TypeBinary + flatbuf.BinaryStart(fv.b) + fv.offset = flatbuf.BinaryEnd(fv.b) + + case *arrow.LargeBinaryType: + fv.dtype = flatbuf.TypeLargeBinary + flatbuf.LargeBinaryStart(fv.b) + fv.offset = flatbuf.LargeBinaryEnd(fv.b) + + case *arrow.StringType: + fv.dtype = flatbuf.TypeUtf8 + flatbuf.Utf8Start(fv.b) + fv.offset = flatbuf.Utf8End(fv.b) + + case *arrow.LargeStringType: + fv.dtype = flatbuf.TypeLargeUtf8 + flatbuf.LargeUtf8Start(fv.b) + fv.offset = flatbuf.LargeUtf8End(fv.b) + + case *arrow.Date32Type: + fv.dtype = flatbuf.TypeDate + flatbuf.DateStart(fv.b) + flatbuf.DateAddUnit(fv.b, flatbuf.DateUnitDAY) + fv.offset = flatbuf.DateEnd(fv.b) + + case *arrow.Date64Type: + fv.dtype = flatbuf.TypeDate + flatbuf.DateStart(fv.b) + flatbuf.DateAddUnit(fv.b, flatbuf.DateUnitMILLISECOND) + fv.offset = flatbuf.DateEnd(fv.b) + + case *arrow.Time32Type: + fv.dtype = flatbuf.TypeTime + flatbuf.TimeStart(fv.b) + flatbuf.TimeAddUnit(fv.b, unitToFB(dt.Unit)) + flatbuf.TimeAddBitWidth(fv.b, 32) + fv.offset = flatbuf.TimeEnd(fv.b) + + case *arrow.Time64Type: + fv.dtype = flatbuf.TypeTime + flatbuf.TimeStart(fv.b) + flatbuf.TimeAddUnit(fv.b, unitToFB(dt.Unit)) + flatbuf.TimeAddBitWidth(fv.b, 64) + fv.offset = flatbuf.TimeEnd(fv.b) + + case *arrow.TimestampType: + fv.dtype = flatbuf.TypeTimestamp + unit := unitToFB(dt.Unit) + var tz flatbuffers.UOffsetT + if dt.TimeZone != "" { + tz = fv.b.CreateString(dt.TimeZone) + } + flatbuf.TimestampStart(fv.b) + flatbuf.TimestampAddUnit(fv.b, unit) + flatbuf.TimestampAddTimezone(fv.b, tz) + fv.offset = flatbuf.TimestampEnd(fv.b) + + case *arrow.StructType: + fv.dtype = flatbuf.TypeStruct_ + offsets := make([]flatbuffers.UOffsetT, len(dt.Fields())) + for i, field := range dt.Fields() { + offsets[i] = fieldToFB(fv.b, fv.pos.Child(int32(i)), field, fv.memo) + } + flatbuf.Struct_Start(fv.b) + for i := len(offsets) - 1; i >= 0; i-- { + fv.b.PrependUOffsetT(offsets[i]) + } + fv.offset = flatbuf.Struct_End(fv.b) + fv.kids = append(fv.kids, offsets...) + + case *arrow.ListType: + fv.dtype = flatbuf.TypeList + fv.kids = append(fv.kids, fieldToFB(fv.b, fv.pos.Child(0), dt.ElemField(), fv.memo)) + flatbuf.ListStart(fv.b) + fv.offset = flatbuf.ListEnd(fv.b) + + case *arrow.LargeListType: + fv.dtype = flatbuf.TypeLargeList + fv.kids = append(fv.kids, fieldToFB(fv.b, fv.pos.Child(0), dt.ElemField(), fv.memo)) + flatbuf.LargeListStart(fv.b) + fv.offset = flatbuf.LargeListEnd(fv.b) + + case *arrow.ListViewType: + fv.dtype = flatbuf.TypeListView + fv.kids = append(fv.kids, fieldToFB(fv.b, fv.pos.Child(0), dt.ElemField(), fv.memo)) + flatbuf.ListViewStart(fv.b) + fv.offset = flatbuf.ListViewEnd(fv.b) + + case *arrow.LargeListViewType: + fv.dtype = flatbuf.TypeLargeListView + fv.kids = append(fv.kids, fieldToFB(fv.b, fv.pos.Child(0), dt.ElemField(), fv.memo)) + flatbuf.LargeListViewStart(fv.b) + fv.offset = flatbuf.LargeListViewEnd(fv.b) + + case *arrow.FixedSizeListType: + fv.dtype = flatbuf.TypeFixedSizeList + fv.kids = append(fv.kids, fieldToFB(fv.b, fv.pos.Child(0), dt.ElemField(), fv.memo)) + flatbuf.FixedSizeListStart(fv.b) + flatbuf.FixedSizeListAddListSize(fv.b, dt.Len()) + fv.offset = flatbuf.FixedSizeListEnd(fv.b) + + case *arrow.MonthIntervalType: + fv.dtype = flatbuf.TypeInterval + flatbuf.IntervalStart(fv.b) + flatbuf.IntervalAddUnit(fv.b, flatbuf.IntervalUnitYEAR_MONTH) + fv.offset = flatbuf.IntervalEnd(fv.b) + + case *arrow.DayTimeIntervalType: + fv.dtype = flatbuf.TypeInterval + flatbuf.IntervalStart(fv.b) + flatbuf.IntervalAddUnit(fv.b, flatbuf.IntervalUnitDAY_TIME) + fv.offset = flatbuf.IntervalEnd(fv.b) + + case *arrow.MonthDayNanoIntervalType: + fv.dtype = flatbuf.TypeInterval + flatbuf.IntervalStart(fv.b) + flatbuf.IntervalAddUnit(fv.b, flatbuf.IntervalUnitMONTH_DAY_NANO) + fv.offset = flatbuf.IntervalEnd(fv.b) + + case *arrow.DurationType: + fv.dtype = flatbuf.TypeDuration + unit := unitToFB(dt.Unit) + flatbuf.DurationStart(fv.b) + flatbuf.DurationAddUnit(fv.b, unit) + fv.offset = flatbuf.DurationEnd(fv.b) + + case *arrow.MapType: + fv.dtype = flatbuf.TypeMap + fv.kids = append(fv.kids, fieldToFB(fv.b, fv.pos.Child(0), dt.ElemField(), fv.memo)) + flatbuf.MapStart(fv.b) + flatbuf.MapAddKeysSorted(fv.b, dt.KeysSorted) + fv.offset = flatbuf.MapEnd(fv.b) + + case *arrow.RunEndEncodedType: + fv.dtype = flatbuf.TypeRunEndEncoded + var offsets [2]flatbuffers.UOffsetT + offsets[0] = fieldToFB(fv.b, fv.pos.Child(0), + arrow.Field{Name: "run_ends", Type: dt.RunEnds()}, fv.memo) + offsets[1] = fieldToFB(fv.b, fv.pos.Child(1), + arrow.Field{Name: "values", Type: dt.Encoded(), Nullable: true}, fv.memo) + flatbuf.RunEndEncodedStart(fv.b) + fv.b.PrependUOffsetT(offsets[1]) + fv.b.PrependUOffsetT(offsets[0]) + fv.offset = flatbuf.RunEndEncodedEnd(fv.b) + fv.kids = append(fv.kids, offsets[0], offsets[1]) + + case arrow.ExtensionType: + field.Type = dt.StorageType() + fv.visit(field) + fv.meta[ExtensionTypeKeyName] = dt.ExtensionName() + fv.meta[ExtensionMetadataKeyName] = string(dt.Serialize()) + + case *arrow.DictionaryType: + field.Type = dt.ValueType + fv.visit(field) + + case arrow.UnionType: + fv.dtype = flatbuf.TypeUnion + offsets := make([]flatbuffers.UOffsetT, len(dt.Fields())) + for i, field := range dt.Fields() { + offsets[i] = fieldToFB(fv.b, fv.pos.Child(int32(i)), field, fv.memo) + } + + codes := dt.TypeCodes() + flatbuf.UnionStartTypeIdsVector(fv.b, len(codes)) + + for i := len(codes) - 1; i >= 0; i-- { + fv.b.PlaceInt32(int32(codes[i])) + } + fbTypeIDs := fv.b.EndVector(len(dt.TypeCodes())) + flatbuf.UnionStart(fv.b) + switch dt.Mode() { + case arrow.SparseMode: + flatbuf.UnionAddMode(fv.b, flatbuf.UnionModeSparse) + case arrow.DenseMode: + flatbuf.UnionAddMode(fv.b, flatbuf.UnionModeDense) + default: + panic("invalid union mode") + } + flatbuf.UnionAddTypeIds(fv.b, fbTypeIDs) + fv.offset = flatbuf.UnionEnd(fv.b) + fv.kids = append(fv.kids, offsets...) + + default: + err := fmt.Errorf("arrow/ipc: invalid data type %v", dt) + panic(err) // FIXME(sbinet): implement all data-types. + } +} + +func (fv *fieldVisitor) result(field arrow.Field) flatbuffers.UOffsetT { + nameFB := fv.b.CreateString(field.Name) + + fv.visit(field) + + flatbuf.FieldStartChildrenVector(fv.b, len(fv.kids)) + for i := len(fv.kids) - 1; i >= 0; i-- { + fv.b.PrependUOffsetT(fv.kids[i]) + } + kidsFB := fv.b.EndVector(len(fv.kids)) + + storageType := field.Type + if storageType.ID() == arrow.EXTENSION { + storageType = storageType.(arrow.ExtensionType).StorageType() + } + + var dictFB flatbuffers.UOffsetT + if storageType.ID() == arrow.DICTIONARY { + idxType := field.Type.(*arrow.DictionaryType).IndexType.(arrow.FixedWidthDataType) + + dictID, err := fv.memo.GetFieldID(fv.pos.Path()) + if err != nil { + panic(err) + } + var signed bool + switch idxType.ID() { + case arrow.UINT8, arrow.UINT16, arrow.UINT32, arrow.UINT64: + signed = false + case arrow.INT8, arrow.INT16, arrow.INT32, arrow.INT64: + signed = true + } + indexTypeOffset := intToFB(fv.b, int32(idxType.BitWidth()), signed) + flatbuf.DictionaryEncodingStart(fv.b) + flatbuf.DictionaryEncodingAddId(fv.b, dictID) + flatbuf.DictionaryEncodingAddIndexType(fv.b, indexTypeOffset) + flatbuf.DictionaryEncodingAddIsOrdered(fv.b, field.Type.(*arrow.DictionaryType).Ordered) + dictFB = flatbuf.DictionaryEncodingEnd(fv.b) + } + + var ( + metaFB flatbuffers.UOffsetT + kvs []flatbuffers.UOffsetT + ) + for i, k := range field.Metadata.Keys() { + v := field.Metadata.Values()[i] + kk := fv.b.CreateString(k) + vv := fv.b.CreateString(v) + flatbuf.KeyValueStart(fv.b) + flatbuf.KeyValueAddKey(fv.b, kk) + flatbuf.KeyValueAddValue(fv.b, vv) + kvs = append(kvs, flatbuf.KeyValueEnd(fv.b)) + } + { + keys := make([]string, 0, len(fv.meta)) + for k := range fv.meta { + keys = append(keys, k) + } + sort.Strings(keys) + for _, k := range keys { + v := fv.meta[k] + kk := fv.b.CreateString(k) + vv := fv.b.CreateString(v) + flatbuf.KeyValueStart(fv.b) + flatbuf.KeyValueAddKey(fv.b, kk) + flatbuf.KeyValueAddValue(fv.b, vv) + kvs = append(kvs, flatbuf.KeyValueEnd(fv.b)) + } + } + if len(kvs) > 0 { + flatbuf.FieldStartCustomMetadataVector(fv.b, len(kvs)) + for i := len(kvs) - 1; i >= 0; i-- { + fv.b.PrependUOffsetT(kvs[i]) + } + metaFB = fv.b.EndVector(len(kvs)) + } + + flatbuf.FieldStart(fv.b) + flatbuf.FieldAddName(fv.b, nameFB) + flatbuf.FieldAddNullable(fv.b, field.Nullable) + flatbuf.FieldAddTypeType(fv.b, fv.dtype) + flatbuf.FieldAddType(fv.b, fv.offset) + flatbuf.FieldAddDictionary(fv.b, dictFB) + flatbuf.FieldAddChildren(fv.b, kidsFB) + flatbuf.FieldAddCustomMetadata(fv.b, metaFB) + + offset := flatbuf.FieldEnd(fv.b) + + return offset +} + +func typeFromFB(field *flatbuf.Field, pos dictutils.FieldPos, children []arrow.Field, md *arrow.Metadata, memo *dictutils.Memo) (arrow.DataType, error) { + var data flatbuffers.Table + if !field.Type(&data) { + return nil, fmt.Errorf("arrow/ipc: could not load field type data") + } + + dt, err := concreteTypeFromFB(field.TypeType(), data, children) + if err != nil { + return dt, err + } + + var ( + dictID = int64(-1) + dictValueType arrow.DataType + encoding = field.Dictionary(nil) + ) + if encoding != nil { + var idt flatbuf.Int + encoding.IndexType(&idt) + idxType, err := intFromFB(idt) + if err != nil { + return nil, err + } + + dictValueType = dt + dt = &arrow.DictionaryType{IndexType: idxType, ValueType: dictValueType, Ordered: encoding.IsOrdered()} + dictID = encoding.Id() + + if err = memo.Mapper.AddField(dictID, pos.Path()); err != nil { + return dt, err + } + if err = memo.AddType(dictID, dictValueType); err != nil { + return dt, err + } + + } + + // look for extension metadata in custom metadata field. + if md.Len() > 0 { + i := md.FindKey(ExtensionTypeKeyName) + if i < 0 { + return dt, err + } + + extType := arrow.GetExtensionType(md.Values()[i]) + if extType == nil { + // if the extension type is unknown, we do not error here. + // simply return the storage type. + return dt, err + } + + var ( + data string + dataIdx int + ) + + if dataIdx = md.FindKey(ExtensionMetadataKeyName); dataIdx >= 0 { + data = md.Values()[dataIdx] + } + + dt, err = extType.Deserialize(dt, data) + if err != nil { + return dt, err + } + + mdkeys := md.Keys() + mdvals := md.Values() + if dataIdx < 0 { + // if there was no extension metadata, just the name, we only have to + // remove the extension name metadata key/value to ensure roundtrip + // metadata consistency + *md = arrow.NewMetadata(append(mdkeys[:i], mdkeys[i+1:]...), append(mdvals[:i], mdvals[i+1:]...)) + } else { + // if there was extension metadata, we need to remove both the type name + // and the extension metadata keys and values. + newkeys := make([]string, 0, md.Len()-2) + newvals := make([]string, 0, md.Len()-2) + for j := range mdkeys { + if j != i && j != dataIdx { // copy everything except the extension metadata keys/values + newkeys = append(newkeys, mdkeys[j]) + newvals = append(newvals, mdvals[j]) + } + } + *md = arrow.NewMetadata(newkeys, newvals) + } + } + + return dt, err +} + +func concreteTypeFromFB(typ flatbuf.Type, data flatbuffers.Table, children []arrow.Field) (arrow.DataType, error) { + switch typ { + case flatbuf.TypeNONE: + return nil, fmt.Errorf("arrow/ipc: Type metadata cannot be none") + + case flatbuf.TypeNull: + return arrow.Null, nil + + case flatbuf.TypeInt: + var dt flatbuf.Int + dt.Init(data.Bytes, data.Pos) + return intFromFB(dt) + + case flatbuf.TypeFloatingPoint: + var dt flatbuf.FloatingPoint + dt.Init(data.Bytes, data.Pos) + return floatFromFB(dt) + + case flatbuf.TypeDecimal: + var dt flatbuf.Decimal + dt.Init(data.Bytes, data.Pos) + return decimalFromFB(dt) + + case flatbuf.TypeBinary: + return arrow.BinaryTypes.Binary, nil + + case flatbuf.TypeFixedSizeBinary: + var dt flatbuf.FixedSizeBinary + dt.Init(data.Bytes, data.Pos) + return &arrow.FixedSizeBinaryType{ByteWidth: int(dt.ByteWidth())}, nil + + case flatbuf.TypeUtf8: + return arrow.BinaryTypes.String, nil + + case flatbuf.TypeLargeBinary: + return arrow.BinaryTypes.LargeBinary, nil + + case flatbuf.TypeLargeUtf8: + return arrow.BinaryTypes.LargeString, nil + + case flatbuf.TypeBool: + return arrow.FixedWidthTypes.Boolean, nil + + case flatbuf.TypeList: + if len(children) != 1 { + return nil, fmt.Errorf("arrow/ipc: List must have exactly 1 child field (got=%d)", len(children)) + } + dt := arrow.ListOfField(children[0]) + return dt, nil + + case flatbuf.TypeLargeList: + if len(children) != 1 { + return nil, fmt.Errorf("arrow/ipc: LargeList must have exactly 1 child field (got=%d)", len(children)) + } + dt := arrow.LargeListOfField(children[0]) + return dt, nil + + case flatbuf.TypeListView: + if len(children) != 1 { + return nil, fmt.Errorf("arrow/ipc: ListView must have exactly 1 child field (got=%d)", len(children)) + } + dt := arrow.ListViewOfField(children[0]) + return dt, nil + + case flatbuf.TypeLargeListView: + if len(children) != 1 { + return nil, fmt.Errorf("arrow/ipc: LargeListView must have exactly 1 child field (got=%d)", len(children)) + } + dt := arrow.LargeListViewOfField(children[0]) + return dt, nil + + case flatbuf.TypeFixedSizeList: + var dt flatbuf.FixedSizeList + dt.Init(data.Bytes, data.Pos) + if len(children) != 1 { + return nil, fmt.Errorf("arrow/ipc: FixedSizeList must have exactly 1 child field (got=%d)", len(children)) + } + ret := arrow.FixedSizeListOfField(dt.ListSize(), children[0]) + return ret, nil + + case flatbuf.TypeStruct_: + return arrow.StructOf(children...), nil + + case flatbuf.TypeUnion: + var dt flatbuf.Union + dt.Init(data.Bytes, data.Pos) + var ( + mode arrow.UnionMode + typeIDs []arrow.UnionTypeCode + ) + + switch dt.Mode() { + case flatbuf.UnionModeSparse: + mode = arrow.SparseMode + case flatbuf.UnionModeDense: + mode = arrow.DenseMode + } + + typeIDLen := dt.TypeIdsLength() + + if typeIDLen == 0 { + for i := range children { + typeIDs = append(typeIDs, int8(i)) + } + } else { + for i := 0; i < typeIDLen; i++ { + id := dt.TypeIds(i) + code := arrow.UnionTypeCode(id) + if int32(code) != id { + return nil, errors.New("union type id out of bounds") + } + typeIDs = append(typeIDs, code) + } + } + + return arrow.UnionOf(mode, children, typeIDs), nil + + case flatbuf.TypeTime: + var dt flatbuf.Time + dt.Init(data.Bytes, data.Pos) + return timeFromFB(dt) + + case flatbuf.TypeTimestamp: + var dt flatbuf.Timestamp + dt.Init(data.Bytes, data.Pos) + return timestampFromFB(dt) + + case flatbuf.TypeDate: + var dt flatbuf.Date + dt.Init(data.Bytes, data.Pos) + return dateFromFB(dt) + + case flatbuf.TypeInterval: + var dt flatbuf.Interval + dt.Init(data.Bytes, data.Pos) + return intervalFromFB(dt) + + case flatbuf.TypeDuration: + var dt flatbuf.Duration + dt.Init(data.Bytes, data.Pos) + return durationFromFB(dt) + + case flatbuf.TypeMap: + if len(children) != 1 { + return nil, fmt.Errorf("arrow/ipc: Map must have exactly 1 child field") + } + + if children[0].Nullable || children[0].Type.ID() != arrow.STRUCT || len(children[0].Type.(*arrow.StructType).Fields()) != 2 { + return nil, fmt.Errorf("arrow/ipc: Map's key-item pairs must be non-nullable structs") + } + + pairType := children[0].Type.(*arrow.StructType) + if pairType.Field(0).Nullable { + return nil, fmt.Errorf("arrow/ipc: Map's keys must be non-nullable") + } + + var dt flatbuf.Map + dt.Init(data.Bytes, data.Pos) + ret := arrow.MapOf(pairType.Field(0).Type, pairType.Field(1).Type) + ret.SetItemNullable(pairType.Field(1).Nullable) + ret.KeysSorted = dt.KeysSorted() + return ret, nil + + case flatbuf.TypeRunEndEncoded: + if len(children) != 2 { + return nil, fmt.Errorf("%w: arrow/ipc: RunEndEncoded must have exactly 2 child fields", arrow.ErrInvalid) + } + switch children[0].Type.ID() { + case arrow.INT16, arrow.INT32, arrow.INT64: + default: + return nil, fmt.Errorf("%w: arrow/ipc: run-end encoded run_ends field must be one of int16, int32, or int64 type", arrow.ErrInvalid) + } + return arrow.RunEndEncodedOf(children[0].Type, children[1].Type), nil + + default: + panic(fmt.Errorf("arrow/ipc: type %v not implemented", flatbuf.EnumNamesType[typ])) + } +} + +func intFromFB(data flatbuf.Int) (arrow.DataType, error) { + bw := data.BitWidth() + if bw > 64 { + return nil, fmt.Errorf("arrow/ipc: integers with more than 64 bits not implemented (bits=%d)", bw) + } + if bw < 8 { + return nil, fmt.Errorf("arrow/ipc: integers with less than 8 bits not implemented (bits=%d)", bw) + } + + switch bw { + case 8: + if !data.IsSigned() { + return arrow.PrimitiveTypes.Uint8, nil + } + return arrow.PrimitiveTypes.Int8, nil + + case 16: + if !data.IsSigned() { + return arrow.PrimitiveTypes.Uint16, nil + } + return arrow.PrimitiveTypes.Int16, nil + + case 32: + if !data.IsSigned() { + return arrow.PrimitiveTypes.Uint32, nil + } + return arrow.PrimitiveTypes.Int32, nil + + case 64: + if !data.IsSigned() { + return arrow.PrimitiveTypes.Uint64, nil + } + return arrow.PrimitiveTypes.Int64, nil + default: + return nil, fmt.Errorf("arrow/ipc: integers not in cstdint are not implemented") + } +} + +func intToFB(b *flatbuffers.Builder, bw int32, isSigned bool) flatbuffers.UOffsetT { + flatbuf.IntStart(b) + flatbuf.IntAddBitWidth(b, bw) + flatbuf.IntAddIsSigned(b, isSigned) + return flatbuf.IntEnd(b) +} + +func floatFromFB(data flatbuf.FloatingPoint) (arrow.DataType, error) { + switch p := data.Precision(); p { + case flatbuf.PrecisionHALF: + return arrow.FixedWidthTypes.Float16, nil + case flatbuf.PrecisionSINGLE: + return arrow.PrimitiveTypes.Float32, nil + case flatbuf.PrecisionDOUBLE: + return arrow.PrimitiveTypes.Float64, nil + default: + return nil, fmt.Errorf("arrow/ipc: floating point type with %d precision not implemented", p) + } +} + +func floatToFB(b *flatbuffers.Builder, bw int32) flatbuffers.UOffsetT { + switch bw { + case 16: + flatbuf.FloatingPointStart(b) + flatbuf.FloatingPointAddPrecision(b, flatbuf.PrecisionHALF) + return flatbuf.FloatingPointEnd(b) + case 32: + flatbuf.FloatingPointStart(b) + flatbuf.FloatingPointAddPrecision(b, flatbuf.PrecisionSINGLE) + return flatbuf.FloatingPointEnd(b) + case 64: + flatbuf.FloatingPointStart(b) + flatbuf.FloatingPointAddPrecision(b, flatbuf.PrecisionDOUBLE) + return flatbuf.FloatingPointEnd(b) + default: + panic(fmt.Errorf("arrow/ipc: invalid floating point precision %d-bits", bw)) + } +} + +func decimalFromFB(data flatbuf.Decimal) (arrow.DataType, error) { + switch data.BitWidth() { + case 128: + return &arrow.Decimal128Type{Precision: data.Precision(), Scale: data.Scale()}, nil + case 256: + return &arrow.Decimal256Type{Precision: data.Precision(), Scale: data.Scale()}, nil + default: + return nil, fmt.Errorf("arrow/ipc: invalid decimal bitwidth: %d", data.BitWidth()) + } +} + +func timeFromFB(data flatbuf.Time) (arrow.DataType, error) { + bw := data.BitWidth() + unit := unitFromFB(data.Unit()) + + switch bw { + case 32: + switch unit { + case arrow.Millisecond: + return arrow.FixedWidthTypes.Time32ms, nil + case arrow.Second: + return arrow.FixedWidthTypes.Time32s, nil + default: + return nil, fmt.Errorf("arrow/ipc: Time32 type with %v unit not implemented", unit) + } + case 64: + switch unit { + case arrow.Nanosecond: + return arrow.FixedWidthTypes.Time64ns, nil + case arrow.Microsecond: + return arrow.FixedWidthTypes.Time64us, nil + default: + return nil, fmt.Errorf("arrow/ipc: Time64 type with %v unit not implemented", unit) + } + default: + return nil, fmt.Errorf("arrow/ipc: Time type with %d bitwidth not implemented", bw) + } +} + +func timestampFromFB(data flatbuf.Timestamp) (arrow.DataType, error) { + unit := unitFromFB(data.Unit()) + tz := string(data.Timezone()) + return &arrow.TimestampType{Unit: unit, TimeZone: tz}, nil +} + +func dateFromFB(data flatbuf.Date) (arrow.DataType, error) { + switch data.Unit() { + case flatbuf.DateUnitDAY: + return arrow.FixedWidthTypes.Date32, nil + case flatbuf.DateUnitMILLISECOND: + return arrow.FixedWidthTypes.Date64, nil + } + return nil, fmt.Errorf("arrow/ipc: Date type with %d unit not implemented", data.Unit()) +} + +func intervalFromFB(data flatbuf.Interval) (arrow.DataType, error) { + switch data.Unit() { + case flatbuf.IntervalUnitYEAR_MONTH: + return arrow.FixedWidthTypes.MonthInterval, nil + case flatbuf.IntervalUnitDAY_TIME: + return arrow.FixedWidthTypes.DayTimeInterval, nil + case flatbuf.IntervalUnitMONTH_DAY_NANO: + return arrow.FixedWidthTypes.MonthDayNanoInterval, nil + } + return nil, fmt.Errorf("arrow/ipc: Interval type with %d unit not implemented", data.Unit()) +} + +func durationFromFB(data flatbuf.Duration) (arrow.DataType, error) { + switch data.Unit() { + case flatbuf.TimeUnitSECOND: + return arrow.FixedWidthTypes.Duration_s, nil + case flatbuf.TimeUnitMILLISECOND: + return arrow.FixedWidthTypes.Duration_ms, nil + case flatbuf.TimeUnitMICROSECOND: + return arrow.FixedWidthTypes.Duration_us, nil + case flatbuf.TimeUnitNANOSECOND: + return arrow.FixedWidthTypes.Duration_ns, nil + } + return nil, fmt.Errorf("arrow/ipc: Duration type with %d unit not implemented", data.Unit()) +} + +type customMetadataer interface { + CustomMetadataLength() int + CustomMetadata(*flatbuf.KeyValue, int) bool +} + +func metadataFromFB(md customMetadataer) (arrow.Metadata, error) { + var ( + keys = make([]string, md.CustomMetadataLength()) + vals = make([]string, md.CustomMetadataLength()) + ) + + for i := range keys { + var kv flatbuf.KeyValue + if !md.CustomMetadata(&kv, i) { + return arrow.Metadata{}, fmt.Errorf("arrow/ipc: could not read key-value %d from flatbuffer", i) + } + keys[i] = string(kv.Key()) + vals[i] = string(kv.Value()) + } + + return arrow.NewMetadata(keys, vals), nil +} + +func metadataToFB(b *flatbuffers.Builder, meta arrow.Metadata, start startVecFunc) flatbuffers.UOffsetT { + if meta.Len() == 0 { + return 0 + } + + n := meta.Len() + kvs := make([]flatbuffers.UOffsetT, n) + for i := range kvs { + k := b.CreateString(meta.Keys()[i]) + v := b.CreateString(meta.Values()[i]) + flatbuf.KeyValueStart(b) + flatbuf.KeyValueAddKey(b, k) + flatbuf.KeyValueAddValue(b, v) + kvs[i] = flatbuf.KeyValueEnd(b) + } + + start(b, n) + for i := n - 1; i >= 0; i-- { + b.PrependUOffsetT(kvs[i]) + } + return b.EndVector(n) +} + +func schemaFromFB(schema *flatbuf.Schema, memo *dictutils.Memo) (*arrow.Schema, error) { + var ( + err error + fields = make([]arrow.Field, schema.FieldsLength()) + pos = dictutils.NewFieldPos() + ) + + for i := range fields { + var field flatbuf.Field + if !schema.Fields(&field, i) { + return nil, fmt.Errorf("arrow/ipc: could not read field %d from schema", i) + } + + fields[i], err = fieldFromFB(&field, pos.Child(int32(i)), memo) + if err != nil { + return nil, fmt.Errorf("arrow/ipc: could not convert field %d from flatbuf: %w", i, err) + } + } + + md, err := metadataFromFB(schema) + if err != nil { + return nil, fmt.Errorf("arrow/ipc: could not convert schema metadata from flatbuf: %w", err) + } + + return arrow.NewSchemaWithEndian(fields, &md, endian.Endianness(schema.Endianness())), nil +} + +func schemaToFB(b *flatbuffers.Builder, schema *arrow.Schema, memo *dictutils.Mapper) flatbuffers.UOffsetT { + fields := make([]flatbuffers.UOffsetT, len(schema.Fields())) + pos := dictutils.NewFieldPos() + for i, field := range schema.Fields() { + fields[i] = fieldToFB(b, pos.Child(int32(i)), field, memo) + } + + flatbuf.SchemaStartFieldsVector(b, len(fields)) + for i := len(fields) - 1; i >= 0; i-- { + b.PrependUOffsetT(fields[i]) + } + fieldsFB := b.EndVector(len(fields)) + + metaFB := metadataToFB(b, schema.Metadata(), flatbuf.SchemaStartCustomMetadataVector) + + flatbuf.SchemaStart(b) + flatbuf.SchemaAddEndianness(b, flatbuf.Endianness(schema.Endianness())) + flatbuf.SchemaAddFields(b, fieldsFB) + flatbuf.SchemaAddCustomMetadata(b, metaFB) + offset := flatbuf.SchemaEnd(b) + + return offset +} + +// payloadFromSchema returns a slice of payloads corresponding to the given schema. +// Callers of payloadFromSchema will need to call Release after use. +func payloadFromSchema(schema *arrow.Schema, mem memory.Allocator, memo *dictutils.Mapper) payloads { + ps := make(payloads, 1) + ps[0].msg = MessageSchema + ps[0].meta = writeSchemaMessage(schema, mem, memo) + + return ps +} + +func writeFBBuilder(b *flatbuffers.Builder, mem memory.Allocator) *memory.Buffer { + raw := b.FinishedBytes() + buf := memory.NewResizableBuffer(mem) + buf.Resize(len(raw)) + copy(buf.Bytes(), raw) + return buf +} + +func writeMessageFB(b *flatbuffers.Builder, mem memory.Allocator, hdrType flatbuf.MessageHeader, hdr flatbuffers.UOffsetT, bodyLen int64) *memory.Buffer { + + flatbuf.MessageStart(b) + flatbuf.MessageAddVersion(b, flatbuf.MetadataVersion(currentMetadataVersion)) + flatbuf.MessageAddHeaderType(b, hdrType) + flatbuf.MessageAddHeader(b, hdr) + flatbuf.MessageAddBodyLength(b, bodyLen) + msg := flatbuf.MessageEnd(b) + b.Finish(msg) + + return writeFBBuilder(b, mem) +} + +func writeSchemaMessage(schema *arrow.Schema, mem memory.Allocator, dict *dictutils.Mapper) *memory.Buffer { + b := flatbuffers.NewBuilder(1024) + schemaFB := schemaToFB(b, schema, dict) + return writeMessageFB(b, mem, flatbuf.MessageHeaderSchema, schemaFB, 0) +} + +func writeFileFooter(schema *arrow.Schema, dicts, recs []fileBlock, w io.Writer) error { + var ( + b = flatbuffers.NewBuilder(1024) + memo dictutils.Mapper + ) + memo.ImportSchema(schema) + + schemaFB := schemaToFB(b, schema, &memo) + dictsFB := fileBlocksToFB(b, dicts, flatbuf.FooterStartDictionariesVector) + recsFB := fileBlocksToFB(b, recs, flatbuf.FooterStartRecordBatchesVector) + + flatbuf.FooterStart(b) + flatbuf.FooterAddVersion(b, flatbuf.MetadataVersion(currentMetadataVersion)) + flatbuf.FooterAddSchema(b, schemaFB) + flatbuf.FooterAddDictionaries(b, dictsFB) + flatbuf.FooterAddRecordBatches(b, recsFB) + footer := flatbuf.FooterEnd(b) + + b.Finish(footer) + + _, err := w.Write(b.FinishedBytes()) + return err +} + +func writeRecordMessage(mem memory.Allocator, size, bodyLength int64, fields []fieldMetadata, meta []bufferMetadata, codec flatbuf.CompressionType) *memory.Buffer { + b := flatbuffers.NewBuilder(0) + recFB := recordToFB(b, size, bodyLength, fields, meta, codec) + return writeMessageFB(b, mem, flatbuf.MessageHeaderRecordBatch, recFB, bodyLength) +} + +func writeDictionaryMessage(mem memory.Allocator, id int64, isDelta bool, size, bodyLength int64, fields []fieldMetadata, meta []bufferMetadata, codec flatbuf.CompressionType) *memory.Buffer { + b := flatbuffers.NewBuilder(0) + recFB := recordToFB(b, size, bodyLength, fields, meta, codec) + + flatbuf.DictionaryBatchStart(b) + flatbuf.DictionaryBatchAddId(b, id) + flatbuf.DictionaryBatchAddData(b, recFB) + flatbuf.DictionaryBatchAddIsDelta(b, isDelta) + dictFB := flatbuf.DictionaryBatchEnd(b) + return writeMessageFB(b, mem, flatbuf.MessageHeaderDictionaryBatch, dictFB, bodyLength) +} + +func recordToFB(b *flatbuffers.Builder, size, bodyLength int64, fields []fieldMetadata, meta []bufferMetadata, codec flatbuf.CompressionType) flatbuffers.UOffsetT { + fieldsFB := writeFieldNodes(b, fields, flatbuf.RecordBatchStartNodesVector) + metaFB := writeBuffers(b, meta, flatbuf.RecordBatchStartBuffersVector) + var bodyCompressFB flatbuffers.UOffsetT + if codec != -1 { + bodyCompressFB = writeBodyCompression(b, codec) + } + + flatbuf.RecordBatchStart(b) + flatbuf.RecordBatchAddLength(b, size) + flatbuf.RecordBatchAddNodes(b, fieldsFB) + flatbuf.RecordBatchAddBuffers(b, metaFB) + if codec != -1 { + flatbuf.RecordBatchAddCompression(b, bodyCompressFB) + } + + return flatbuf.RecordBatchEnd(b) +} + +func writeFieldNodes(b *flatbuffers.Builder, fields []fieldMetadata, start startVecFunc) flatbuffers.UOffsetT { + + start(b, len(fields)) + for i := len(fields) - 1; i >= 0; i-- { + field := fields[i] + if field.Offset != 0 { + panic(fmt.Errorf("arrow/ipc: field metadata for IPC must have offset 0")) + } + flatbuf.CreateFieldNode(b, field.Len, field.Nulls) + } + + return b.EndVector(len(fields)) +} + +func writeBuffers(b *flatbuffers.Builder, buffers []bufferMetadata, start startVecFunc) flatbuffers.UOffsetT { + start(b, len(buffers)) + for i := len(buffers) - 1; i >= 0; i-- { + buffer := buffers[i] + flatbuf.CreateBuffer(b, buffer.Offset, buffer.Len) + } + return b.EndVector(len(buffers)) +} + +func writeBodyCompression(b *flatbuffers.Builder, codec flatbuf.CompressionType) flatbuffers.UOffsetT { + flatbuf.BodyCompressionStart(b) + flatbuf.BodyCompressionAddCodec(b, codec) + flatbuf.BodyCompressionAddMethod(b, flatbuf.BodyCompressionMethodBUFFER) + return flatbuf.BodyCompressionEnd(b) +} + +func writeMessage(msg *memory.Buffer, alignment int32, w io.Writer) (int, error) { + var ( + n int + err error + ) + + // ARROW-3212: we do not make any assumption on whether the output stream is aligned or not. + paddedMsgLen := int32(msg.Len()) + 8 + remainder := paddedMsgLen % alignment + if remainder != 0 { + paddedMsgLen += alignment - remainder + } + + tmp := make([]byte, 4) + + // write continuation indicator, to address 8-byte alignment requirement from FlatBuffers. + binary.LittleEndian.PutUint32(tmp, kIPCContToken) + _, err = w.Write(tmp) + if err != nil { + return 0, fmt.Errorf("arrow/ipc: could not write continuation bit indicator: %w", err) + } + + // the returned message size includes the length prefix, the flatbuffer, + padding + n = int(paddedMsgLen) + + // write the flatbuffer size prefix, including padding + sizeFB := paddedMsgLen - 8 + binary.LittleEndian.PutUint32(tmp, uint32(sizeFB)) + _, err = w.Write(tmp) + if err != nil { + return n, fmt.Errorf("arrow/ipc: could not write message flatbuffer size prefix: %w", err) + } + + // write the flatbuffer + _, err = w.Write(msg.Bytes()) + if err != nil { + return n, fmt.Errorf("arrow/ipc: could not write message flatbuffer: %w", err) + } + + // write any padding + padding := paddedMsgLen - int32(msg.Len()) - 8 + if padding > 0 { + _, err = w.Write(paddingBytes[:padding]) + if err != nil { + return n, fmt.Errorf("arrow/ipc: could not write message padding bytes: %w", err) + } + } + + return n, err +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/ipc/reader.go b/vendor/github.com/apache/arrow/go/v14/arrow/ipc/reader.go new file mode 100644 index 000000000..1f684c1f6 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/ipc/reader.go @@ -0,0 +1,285 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ipc + +import ( + "bytes" + "errors" + "fmt" + "io" + "sync/atomic" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/array" + "github.com/apache/arrow/go/v14/arrow/endian" + "github.com/apache/arrow/go/v14/arrow/internal/debug" + "github.com/apache/arrow/go/v14/arrow/internal/dictutils" + "github.com/apache/arrow/go/v14/arrow/internal/flatbuf" + "github.com/apache/arrow/go/v14/arrow/memory" +) + +// Reader reads records from an io.Reader. +// Reader expects a schema (plus any dictionaries) as the first messages +// in the stream, followed by records. +type Reader struct { + r MessageReader + schema *arrow.Schema + + refCount int64 + rec arrow.Record + err error + + // types dictTypeMap + memo dictutils.Memo + readInitialDicts bool + done bool + swapEndianness bool + ensureNativeEndian bool + expectedSchema *arrow.Schema + + mem memory.Allocator +} + +// NewReaderFromMessageReader allows constructing a new reader object with the +// provided MessageReader allowing injection of reading messages other than +// by simple streaming bytes such as Arrow Flight which receives a protobuf message +func NewReaderFromMessageReader(r MessageReader, opts ...Option) (reader *Reader, err error) { + defer func() { + if pErr := recover(); pErr != nil { + err = fmt.Errorf("arrow/ipc: unknown error while reading: %v", pErr) + } + }() + cfg := newConfig() + for _, opt := range opts { + opt(cfg) + } + + rr := &Reader{ + r: r, + refCount: 1, + // types: make(dictTypeMap), + memo: dictutils.NewMemo(), + mem: cfg.alloc, + ensureNativeEndian: cfg.ensureNativeEndian, + expectedSchema: cfg.schema, + } + + if !cfg.noAutoSchema { + if err := rr.readSchema(cfg.schema); err != nil { + return nil, err + } + } + + return rr, nil +} + +// NewReader returns a reader that reads records from an input stream. +func NewReader(r io.Reader, opts ...Option) (*Reader, error) { + return NewReaderFromMessageReader(NewMessageReader(r, opts...), opts...) +} + +// Err returns the last error encountered during the iteration over the +// underlying stream. +func (r *Reader) Err() error { return r.err } + +func (r *Reader) Schema() *arrow.Schema { + if r.schema == nil { + if err := r.readSchema(r.expectedSchema); err != nil { + r.err = fmt.Errorf("arrow/ipc: could not read schema from stream: %w", err) + r.done = true + } + } + return r.schema +} + +func (r *Reader) readSchema(schema *arrow.Schema) error { + msg, err := r.r.Message() + if err != nil { + return fmt.Errorf("arrow/ipc: could not read message schema: %w", err) + } + + if msg.Type() != MessageSchema { + return fmt.Errorf("arrow/ipc: invalid message type (got=%v, want=%v)", msg.Type(), MessageSchema) + } + + // FIXME(sbinet) refactor msg-header handling. + var schemaFB flatbuf.Schema + initFB(&schemaFB, msg.msg.Header) + + r.schema, err = schemaFromFB(&schemaFB, &r.memo) + if err != nil { + return fmt.Errorf("arrow/ipc: could not decode schema from message schema: %w", err) + } + + // check the provided schema match the one read from stream. + if schema != nil && !schema.Equal(r.schema) { + return errInconsistentSchema + } + + if r.ensureNativeEndian && !r.schema.IsNativeEndian() { + r.swapEndianness = true + r.schema = r.schema.WithEndianness(endian.NativeEndian) + } + + return nil +} + +// Retain increases the reference count by 1. +// Retain may be called simultaneously from multiple goroutines. +func (r *Reader) Retain() { + atomic.AddInt64(&r.refCount, 1) +} + +// Release decreases the reference count by 1. +// When the reference count goes to zero, the memory is freed. +// Release may be called simultaneously from multiple goroutines. +func (r *Reader) Release() { + debug.Assert(atomic.LoadInt64(&r.refCount) > 0, "too many releases") + + if atomic.AddInt64(&r.refCount, -1) == 0 { + if r.rec != nil { + r.rec.Release() + r.rec = nil + } + if r.r != nil { + r.r.Release() + r.r = nil + } + r.memo.Clear() + } +} + +// Next returns whether a Record could be extracted from the underlying stream. +func (r *Reader) Next() bool { + if r.rec != nil { + r.rec.Release() + r.rec = nil + } + + if r.err != nil || r.done { + return false + } + + return r.next() +} + +func (r *Reader) getInitialDicts() bool { + var msg *Message + // we have to get all dictionaries before reconstructing the first + // record. subsequent deltas and replacements modify the memo + numDicts := r.memo.Mapper.NumDicts() + // there should be numDicts dictionary messages + for i := 0; i < numDicts; i++ { + msg, r.err = r.r.Message() + if r.err != nil { + r.done = true + if r.err == io.EOF { + if i == 0 { + r.err = nil + } else { + r.err = fmt.Errorf("arrow/ipc: IPC stream ended without reading the expected (%d) dictionaries", numDicts) + } + } + return false + } + + if msg.Type() != MessageDictionaryBatch { + r.err = fmt.Errorf("arrow/ipc: IPC stream did not have the expected (%d) dictionaries at the start of the stream", numDicts) + } + if _, err := readDictionary(&r.memo, msg.meta, bytes.NewReader(msg.body.Bytes()), r.swapEndianness, r.mem); err != nil { + r.done = true + r.err = err + return false + } + } + r.readInitialDicts = true + return true +} + +func (r *Reader) next() bool { + defer func() { + if pErr := recover(); pErr != nil { + r.err = fmt.Errorf("arrow/ipc: unknown error while reading: %v", pErr) + } + }() + if r.schema == nil { + if err := r.readSchema(r.expectedSchema); err != nil { + r.err = fmt.Errorf("arrow/ipc: could not read schema from stream: %w", err) + r.done = true + return false + } + } + + if !r.readInitialDicts && !r.getInitialDicts() { + return false + } + + var msg *Message + msg, r.err = r.r.Message() + + for msg != nil && msg.Type() == MessageDictionaryBatch { + if _, r.err = readDictionary(&r.memo, msg.meta, bytes.NewReader(msg.body.Bytes()), r.swapEndianness, r.mem); r.err != nil { + r.done = true + return false + } + msg, r.err = r.r.Message() + } + if r.err != nil { + r.done = true + if errors.Is(r.err, io.EOF) { + r.err = nil + } + return false + } + + if got, want := msg.Type(), MessageRecordBatch; got != want { + r.err = fmt.Errorf("arrow/ipc: invalid message type (got=%v, want=%v", got, want) + return false + } + + r.rec = newRecord(r.schema, &r.memo, msg.meta, bytes.NewReader(msg.body.Bytes()), r.swapEndianness, r.mem) + return true +} + +// Record returns the current record that has been extracted from the +// underlying stream. +// It is valid until the next call to Next. +func (r *Reader) Record() arrow.Record { + return r.rec +} + +// Read reads the current record from the underlying stream and an error, if any. +// When the Reader reaches the end of the underlying stream, it returns (nil, io.EOF). +func (r *Reader) Read() (arrow.Record, error) { + if r.rec != nil { + r.rec.Release() + r.rec = nil + } + + if !r.next() { + if r.done && r.err == nil { + return nil, io.EOF + } + return nil, r.err + } + + return r.rec, nil +} + +var ( + _ array.RecordReader = (*Reader)(nil) +) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/ipc/writer.go b/vendor/github.com/apache/arrow/go/v14/arrow/ipc/writer.go new file mode 100644 index 000000000..a97f47ef4 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/ipc/writer.go @@ -0,0 +1,1004 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ipc + +import ( + "context" + "encoding/binary" + "errors" + "fmt" + "io" + "math" + "sync" + "unsafe" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/array" + "github.com/apache/arrow/go/v14/arrow/bitutil" + "github.com/apache/arrow/go/v14/arrow/internal" + "github.com/apache/arrow/go/v14/arrow/internal/debug" + "github.com/apache/arrow/go/v14/arrow/internal/dictutils" + "github.com/apache/arrow/go/v14/arrow/internal/flatbuf" + "github.com/apache/arrow/go/v14/arrow/memory" +) + +type swriter struct { + w io.Writer + pos int64 +} + +func (w *swriter) Start() error { return nil } +func (w *swriter) Close() error { + _, err := w.Write(kEOS[:]) + return err +} + +func (w *swriter) WritePayload(p Payload) error { + _, err := writeIPCPayload(w, p) + if err != nil { + return err + } + return nil +} + +func (w *swriter) Write(p []byte) (int, error) { + n, err := w.w.Write(p) + w.pos += int64(n) + return n, err +} + +func hasNestedDict(data arrow.ArrayData) bool { + if data.DataType().ID() == arrow.DICTIONARY { + return true + } + for _, c := range data.Children() { + if hasNestedDict(c) { + return true + } + } + return false +} + +// Writer is an Arrow stream writer. +type Writer struct { + w io.Writer + + mem memory.Allocator + pw PayloadWriter + + started bool + schema *arrow.Schema + mapper dictutils.Mapper + codec flatbuf.CompressionType + compressNP int + minSpaceSavings *float64 + + // map of the last written dictionaries by id + // so we can avoid writing the same dictionary over and over + lastWrittenDicts map[int64]arrow.Array + emitDictDeltas bool +} + +// NewWriterWithPayloadWriter constructs a writer with the provided payload writer +// instead of the default stream payload writer. This makes the writer more +// reusable such as by the Arrow Flight writer. +func NewWriterWithPayloadWriter(pw PayloadWriter, opts ...Option) *Writer { + cfg := newConfig(opts...) + return &Writer{ + mem: cfg.alloc, + pw: pw, + schema: cfg.schema, + codec: cfg.codec, + compressNP: cfg.compressNP, + minSpaceSavings: cfg.minSpaceSavings, + emitDictDeltas: cfg.emitDictDeltas, + } +} + +// NewWriter returns a writer that writes records to the provided output stream. +func NewWriter(w io.Writer, opts ...Option) *Writer { + cfg := newConfig(opts...) + return &Writer{ + w: w, + mem: cfg.alloc, + pw: &swriter{w: w}, + schema: cfg.schema, + codec: cfg.codec, + emitDictDeltas: cfg.emitDictDeltas, + } +} + +func (w *Writer) Close() error { + if !w.started { + err := w.start() + if err != nil { + return err + } + } + + if w.pw == nil { + return nil + } + + err := w.pw.Close() + if err != nil { + return fmt.Errorf("arrow/ipc: could not close payload writer: %w", err) + } + w.pw = nil + + for _, d := range w.lastWrittenDicts { + d.Release() + } + + return nil +} + +func (w *Writer) Write(rec arrow.Record) (err error) { + defer func() { + if pErr := recover(); pErr != nil { + err = fmt.Errorf("arrow/ipc: unknown error while writing: %v", pErr) + } + }() + + if !w.started { + err := w.start() + if err != nil { + return err + } + } + + schema := rec.Schema() + if schema == nil || !schema.Equal(w.schema) { + return errInconsistentSchema + } + + const allow64b = true + var ( + data = Payload{msg: MessageRecordBatch} + enc = newRecordEncoder(w.mem, 0, kMaxNestingDepth, allow64b, w.codec, w.compressNP, w.minSpaceSavings) + ) + defer data.Release() + + err = writeDictionaryPayloads(w.mem, rec, false, w.emitDictDeltas, &w.mapper, w.lastWrittenDicts, w.pw, enc) + if err != nil { + return fmt.Errorf("arrow/ipc: failure writing dictionary batches: %w", err) + } + + enc.reset() + if err := enc.Encode(&data, rec); err != nil { + return fmt.Errorf("arrow/ipc: could not encode record to payload: %w", err) + } + + return w.pw.WritePayload(data) +} + +func writeDictionaryPayloads(mem memory.Allocator, batch arrow.Record, isFileFormat bool, emitDictDeltas bool, mapper *dictutils.Mapper, lastWrittenDicts map[int64]arrow.Array, pw PayloadWriter, encoder *recordEncoder) error { + dictionaries, err := dictutils.CollectDictionaries(batch, mapper) + if err != nil { + return err + } + defer func() { + for _, d := range dictionaries { + d.Dict.Release() + } + }() + + eqopt := array.WithNaNsEqual(true) + for _, pair := range dictionaries { + encoder.reset() + var ( + deltaStart int64 + enc = dictEncoder{encoder} + ) + lastDict, exists := lastWrittenDicts[pair.ID] + if exists { + if lastDict.Data() == pair.Dict.Data() { + continue + } + newLen, lastLen := pair.Dict.Len(), lastDict.Len() + if lastLen == newLen && array.ApproxEqual(lastDict, pair.Dict, eqopt) { + // same dictionary by value + // might cost CPU, but required for IPC file format + continue + } + if isFileFormat { + return errors.New("arrow/ipc: Dictionary replacement detected when writing IPC file format. Arrow IPC File only supports single dictionary per field") + } + + if newLen > lastLen && + emitDictDeltas && + !hasNestedDict(pair.Dict.Data()) && + (array.SliceApproxEqual(lastDict, 0, int64(lastLen), pair.Dict, 0, int64(lastLen), eqopt)) { + deltaStart = int64(lastLen) + } + } + + var data = Payload{msg: MessageDictionaryBatch} + defer data.Release() + + dict := pair.Dict + if deltaStart > 0 { + dict = array.NewSlice(dict, deltaStart, int64(dict.Len())) + defer dict.Release() + } + if err := enc.Encode(&data, pair.ID, deltaStart > 0, dict); err != nil { + return err + } + + if err := pw.WritePayload(data); err != nil { + return err + } + + lastWrittenDicts[pair.ID] = pair.Dict + if lastDict != nil { + lastDict.Release() + } + pair.Dict.Retain() + } + return nil +} + +func (w *Writer) start() error { + w.started = true + + w.mapper.ImportSchema(w.schema) + w.lastWrittenDicts = make(map[int64]arrow.Array) + + // write out schema payloads + ps := payloadFromSchema(w.schema, w.mem, &w.mapper) + defer ps.Release() + + for _, data := range ps { + err := w.pw.WritePayload(data) + if err != nil { + return err + } + } + + return nil +} + +type dictEncoder struct { + *recordEncoder +} + +func (d *dictEncoder) encodeMetadata(p *Payload, isDelta bool, id, nrows int64) error { + p.meta = writeDictionaryMessage(d.mem, id, isDelta, nrows, p.size, d.fields, d.meta, d.codec) + return nil +} + +func (d *dictEncoder) Encode(p *Payload, id int64, isDelta bool, dict arrow.Array) error { + d.start = 0 + defer func() { + d.start = 0 + }() + + schema := arrow.NewSchema([]arrow.Field{{Name: "dictionary", Type: dict.DataType(), Nullable: true}}, nil) + batch := array.NewRecord(schema, []arrow.Array{dict}, int64(dict.Len())) + defer batch.Release() + if err := d.encode(p, batch); err != nil { + return err + } + + return d.encodeMetadata(p, isDelta, id, batch.NumRows()) +} + +type recordEncoder struct { + mem memory.Allocator + + fields []fieldMetadata + meta []bufferMetadata + + depth int64 + start int64 + allow64b bool + codec flatbuf.CompressionType + compressNP int + minSpaceSavings *float64 +} + +func newRecordEncoder(mem memory.Allocator, startOffset, maxDepth int64, allow64b bool, codec flatbuf.CompressionType, compressNP int, minSpaceSavings *float64) *recordEncoder { + return &recordEncoder{ + mem: mem, + start: startOffset, + depth: maxDepth, + allow64b: allow64b, + codec: codec, + compressNP: compressNP, + minSpaceSavings: minSpaceSavings, + } +} + +func (w *recordEncoder) shouldCompress(uncompressed, compressed int) bool { + debug.Assert(uncompressed > 0, "uncompressed size is 0") + if w.minSpaceSavings == nil { + return true + } + + savings := 1.0 - float64(compressed)/float64(uncompressed) + return savings >= *w.minSpaceSavings +} + +func (w *recordEncoder) reset() { + w.start = 0 + w.fields = make([]fieldMetadata, 0) +} + +func (w *recordEncoder) compressBodyBuffers(p *Payload) error { + compress := func(idx int, codec compressor) error { + if p.body[idx] == nil || p.body[idx].Len() == 0 { + return nil + } + + buf := memory.NewResizableBuffer(w.mem) + buf.Reserve(codec.MaxCompressedLen(p.body[idx].Len()) + arrow.Int64SizeBytes) + + binary.LittleEndian.PutUint64(buf.Buf(), uint64(p.body[idx].Len())) + bw := &bufferWriter{buf: buf, pos: arrow.Int64SizeBytes} + codec.Reset(bw) + + n, err := codec.Write(p.body[idx].Bytes()) + if err != nil { + return err + } + if err := codec.Close(); err != nil { + return err + } + + finalLen := bw.pos + compressedLen := bw.pos - arrow.Int64SizeBytes + if !w.shouldCompress(n, compressedLen) { + n = copy(buf.Buf()[arrow.Int64SizeBytes:], p.body[idx].Bytes()) + // size of -1 indicates to the reader that the body + // doesn't need to be decompressed + var noprefix int64 = -1 + binary.LittleEndian.PutUint64(buf.Buf(), uint64(noprefix)) + finalLen = n + arrow.Int64SizeBytes + } + bw.buf.Resize(finalLen) + p.body[idx].Release() + p.body[idx] = buf + return nil + } + + if w.compressNP <= 1 { + codec := getCompressor(w.codec) + for idx := range p.body { + if err := compress(idx, codec); err != nil { + return err + } + } + return nil + } + + var ( + wg sync.WaitGroup + ch = make(chan int) + errch = make(chan error) + ctx, cancel = context.WithCancel(context.Background()) + ) + defer cancel() + + for i := 0; i < w.compressNP; i++ { + wg.Add(1) + go func() { + defer wg.Done() + codec := getCompressor(w.codec) + for { + select { + case idx, ok := <-ch: + if !ok { + // we're done, channel is closed! + return + } + + if err := compress(idx, codec); err != nil { + errch <- err + cancel() + return + } + case <-ctx.Done(): + // cancelled, return early + return + } + } + }() + } + + for idx := range p.body { + ch <- idx + } + + close(ch) + wg.Wait() + close(errch) + + return <-errch +} + +func (w *recordEncoder) encode(p *Payload, rec arrow.Record) error { + // perform depth-first traversal of the row-batch + for i, col := range rec.Columns() { + err := w.visit(p, col) + if err != nil { + return fmt.Errorf("arrow/ipc: could not encode column %d (%q): %w", i, rec.ColumnName(i), err) + } + } + + if w.codec != -1 { + if w.minSpaceSavings != nil { + pct := *w.minSpaceSavings + if pct < 0 || pct > 1 { + p.Release() + return fmt.Errorf("%w: minSpaceSavings not in range [0,1]. Provided %.05f", + arrow.ErrInvalid, pct) + } + } + w.compressBodyBuffers(p) + } + + // position for the start of a buffer relative to the passed frame of reference. + // may be 0 or some other position in an address space. + offset := w.start + w.meta = make([]bufferMetadata, len(p.body)) + + // construct the metadata for the record batch header + for i, buf := range p.body { + var ( + size int64 + padding int64 + ) + // the buffer might be null if we are handling zero row lengths. + if buf != nil { + size = int64(buf.Len()) + padding = bitutil.CeilByte64(size) - size + } + w.meta[i] = bufferMetadata{ + Offset: offset, + // even though we add padding, we need the Len to be correct + // so that decompressing works properly. + Len: size, + } + offset += size + padding + } + + p.size = offset - w.start + if !bitutil.IsMultipleOf8(p.size) { + panic("not aligned") + } + + return nil +} + +func (w *recordEncoder) visit(p *Payload, arr arrow.Array) error { + if w.depth <= 0 { + return errMaxRecursion + } + + if !w.allow64b && arr.Len() > math.MaxInt32 { + return errBigArray + } + + if arr.DataType().ID() == arrow.EXTENSION { + arr := arr.(array.ExtensionArray) + err := w.visit(p, arr.Storage()) + if err != nil { + return fmt.Errorf("failed visiting storage of for array %T: %w", arr, err) + } + return nil + } + + if arr.DataType().ID() == arrow.DICTIONARY { + arr := arr.(*array.Dictionary) + return w.visit(p, arr.Indices()) + } + + // add all common elements + w.fields = append(w.fields, fieldMetadata{ + Len: int64(arr.Len()), + Nulls: int64(arr.NullN()), + Offset: 0, + }) + + if arr.DataType().ID() == arrow.NULL { + return nil + } + + if internal.HasValidityBitmap(arr.DataType().ID(), flatbuf.MetadataVersion(currentMetadataVersion)) { + switch arr.NullN() { + case 0: + // there are no null values, drop the null bitmap + p.body = append(p.body, nil) + default: + data := arr.Data() + var bitmap *memory.Buffer + if data.NullN() == data.Len() { + // every value is null, just use a new zero-initialized bitmap to avoid the expense of copying + bitmap = memory.NewResizableBuffer(w.mem) + minLength := paddedLength(bitutil.BytesForBits(int64(data.Len())), kArrowAlignment) + bitmap.Resize(int(minLength)) + } else { + // otherwise truncate and copy the bits + bitmap = newTruncatedBitmap(w.mem, int64(data.Offset()), int64(data.Len()), data.Buffers()[0]) + } + p.body = append(p.body, bitmap) + } + } + + switch dtype := arr.DataType().(type) { + case *arrow.NullType: + // ok. NullArrays are completely empty. + + case *arrow.BooleanType: + var ( + data = arr.Data() + bitm *memory.Buffer + ) + + if data.Len() != 0 { + bitm = newTruncatedBitmap(w.mem, int64(data.Offset()), int64(data.Len()), data.Buffers()[1]) + } + p.body = append(p.body, bitm) + + case arrow.FixedWidthDataType: + data := arr.Data() + values := data.Buffers()[1] + arrLen := int64(arr.Len()) + typeWidth := int64(dtype.BitWidth() / 8) + minLength := paddedLength(arrLen*typeWidth, kArrowAlignment) + + switch { + case needTruncate(int64(data.Offset()), values, minLength): + // non-zero offset: slice the buffer + offset := int64(data.Offset()) * typeWidth + // send padding if available + len := minI64(bitutil.CeilByte64(arrLen*typeWidth), int64(values.Len())-offset) + values = memory.NewBufferBytes(values.Bytes()[offset : offset+len]) + default: + if values != nil { + values.Retain() + } + } + p.body = append(p.body, values) + + case *arrow.BinaryType, *arrow.LargeBinaryType, *arrow.StringType, *arrow.LargeStringType: + arr := arr.(array.BinaryLike) + voffsets := w.getZeroBasedValueOffsets(arr) + data := arr.Data() + values := data.Buffers()[2] + + var totalDataBytes int64 + if voffsets != nil { + totalDataBytes = int64(len(arr.ValueBytes())) + } + + switch { + case needTruncate(int64(data.Offset()), values, totalDataBytes): + // slice data buffer to include the range we need now. + var ( + beg = arr.ValueOffset64(0) + len = minI64(paddedLength(totalDataBytes, kArrowAlignment), int64(totalDataBytes)) + ) + values = memory.NewBufferBytes(data.Buffers()[2].Bytes()[beg : beg+len]) + default: + if values != nil { + values.Retain() + } + } + p.body = append(p.body, voffsets) + p.body = append(p.body, values) + + case *arrow.StructType: + w.depth-- + arr := arr.(*array.Struct) + for i := 0; i < arr.NumField(); i++ { + err := w.visit(p, arr.Field(i)) + if err != nil { + return fmt.Errorf("could not visit field %d of struct-array: %w", i, err) + } + } + w.depth++ + + case *arrow.SparseUnionType: + offset, length := arr.Data().Offset(), arr.Len() + arr := arr.(*array.SparseUnion) + typeCodes := getTruncatedBuffer(int64(offset), int64(length), int32(unsafe.Sizeof(arrow.UnionTypeCode(0))), arr.TypeCodes()) + p.body = append(p.body, typeCodes) + + w.depth-- + for i := 0; i < arr.NumFields(); i++ { + err := w.visit(p, arr.Field(i)) + if err != nil { + return fmt.Errorf("could not visit field %d of sparse union array: %w", i, err) + } + } + w.depth++ + case *arrow.DenseUnionType: + offset, length := arr.Data().Offset(), arr.Len() + arr := arr.(*array.DenseUnion) + typeCodes := getTruncatedBuffer(int64(offset), int64(length), int32(unsafe.Sizeof(arrow.UnionTypeCode(0))), arr.TypeCodes()) + p.body = append(p.body, typeCodes) + + w.depth-- + dt := arr.UnionType() + + // union type codes are not necessarily 0-indexed + maxCode := dt.MaxTypeCode() + + // allocate an array of child offsets. Set all to -1 to indicate we + // haven't observed a first occurrence of a particular child yet + offsets := make([]int32, maxCode+1) + lengths := make([]int32, maxCode+1) + offsets[0], lengths[0] = -1, 0 + for i := 1; i < len(offsets); i *= 2 { + copy(offsets[i:], offsets[:i]) + copy(lengths[i:], lengths[:i]) + } + + var valueOffsets *memory.Buffer + if offset != 0 { + valueOffsets = w.rebaseDenseUnionValueOffsets(arr, offsets, lengths) + } else { + valueOffsets = getTruncatedBuffer(int64(offset), int64(length), int32(arrow.Int32SizeBytes), arr.ValueOffsets()) + } + p.body = append(p.body, valueOffsets) + + // visit children and slice accordingly + for i := range dt.Fields() { + child := arr.Field(i) + // for sliced unions it's tricky to know how much to truncate + // the children. For now we'll truncate the children to be + // no longer than the parent union. + + if offset != 0 { + code := dt.TypeCodes()[i] + childOffset := offsets[code] + childLen := lengths[code] + + if childOffset > 0 { + child = array.NewSlice(child, int64(childOffset), int64(childOffset+childLen)) + defer child.Release() + } else if childLen < int32(child.Len()) { + child = array.NewSlice(child, 0, int64(childLen)) + defer child.Release() + } + } + if err := w.visit(p, child); err != nil { + return fmt.Errorf("could not visit field %d of dense union array: %w", i, err) + } + } + w.depth++ + case *arrow.MapType, *arrow.ListType, *arrow.LargeListType: + arr := arr.(array.ListLike) + voffsets := w.getZeroBasedValueOffsets(arr) + p.body = append(p.body, voffsets) + + w.depth-- + var ( + values = arr.ListValues() + mustRelease = false + values_offset int64 + values_end int64 + ) + defer func() { + if mustRelease { + values.Release() + } + }() + + if arr.Len() > 0 && voffsets != nil { + values_offset, _ = arr.ValueOffsets(0) + _, values_end = arr.ValueOffsets(arr.Len() - 1) + } + + if arr.Len() != 0 || values_end < int64(values.Len()) { + // must also slice the values + values = array.NewSlice(values, values_offset, values_end) + mustRelease = true + } + err := w.visit(p, values) + + if err != nil { + return fmt.Errorf("could not visit list element for array %T: %w", arr, err) + } + w.depth++ + + case *arrow.ListViewType, *arrow.LargeListViewType: + data := arr.Data() + arr := arr.(array.VarLenListLike) + offsetTraits := arr.DataType().(arrow.OffsetsDataType).OffsetTypeTraits() + rngOff, rngLen := array.RangeOfValuesUsed(arr) + voffsets := w.getValueOffsetsAtBaseValue(arr, rngOff) + p.body = append(p.body, voffsets) + + vsizes := data.Buffers()[2] + if vsizes != nil { + if data.Offset() != 0 || vsizes.Len() > offsetTraits.BytesRequired(arr.Len()) { + beg := offsetTraits.BytesRequired(data.Offset()) + end := beg + offsetTraits.BytesRequired(data.Len()) + vsizes = memory.NewBufferBytes(vsizes.Bytes()[beg:end]) + } else { + vsizes.Retain() + } + } + p.body = append(p.body, vsizes) + + w.depth-- + var ( + values = arr.ListValues() + mustRelease = false + values_offset = int64(rngOff) + values_end = int64(rngOff + rngLen) + ) + defer func() { + if mustRelease { + values.Release() + } + }() + + if arr.Len() > 0 && values_end < int64(values.Len()) { + // must also slice the values + values = array.NewSlice(values, values_offset, values_end) + mustRelease = true + } + err := w.visit(p, values) + + if err != nil { + return fmt.Errorf("could not visit list element for array %T: %w", arr, err) + } + w.depth++ + + case *arrow.FixedSizeListType: + arr := arr.(*array.FixedSizeList) + + w.depth-- + + size := int64(arr.DataType().(*arrow.FixedSizeListType).Len()) + beg := int64(arr.Offset()) * size + end := int64(arr.Offset()+arr.Len()) * size + + values := array.NewSlice(arr.ListValues(), beg, end) + defer values.Release() + + err := w.visit(p, values) + + if err != nil { + return fmt.Errorf("could not visit list element for array %T: %w", arr, err) + } + w.depth++ + + case *arrow.RunEndEncodedType: + arr := arr.(*array.RunEndEncoded) + w.depth-- + child := arr.LogicalRunEndsArray(w.mem) + defer child.Release() + if err := w.visit(p, child); err != nil { + return err + } + child = arr.LogicalValuesArray() + defer child.Release() + if err := w.visit(p, child); err != nil { + return err + } + w.depth++ + + default: + panic(fmt.Errorf("arrow/ipc: unknown array %T (dtype=%T)", arr, dtype)) + } + + return nil +} + +func (w *recordEncoder) getZeroBasedValueOffsets(arr arrow.Array) *memory.Buffer { + data := arr.Data() + voffsets := data.Buffers()[1] + offsetTraits := arr.DataType().(arrow.OffsetsDataType).OffsetTypeTraits() + offsetBytesNeeded := offsetTraits.BytesRequired(data.Len() + 1) + + if voffsets == nil || voffsets.Len() == 0 { + return nil + } + + // if we have a non-zero offset, then the value offsets do not start at + // zero. we must a) create a new offsets array with shifted offsets and + // b) slice the values array accordingly + // + // or if there are more value offsets than values (the array has been sliced) + // we need to trim off the trailing offsets + needsTruncateAndShift := data.Offset() != 0 || offsetBytesNeeded < voffsets.Len() + + if needsTruncateAndShift { + shiftedOffsets := memory.NewResizableBuffer(w.mem) + shiftedOffsets.Resize(offsetBytesNeeded) + + switch arr.DataType().Layout().Buffers[1].ByteWidth { + case 8: + dest := arrow.Int64Traits.CastFromBytes(shiftedOffsets.Bytes()) + offsets := arrow.Int64Traits.CastFromBytes(voffsets.Bytes())[data.Offset() : data.Offset()+data.Len()+1] + + startOffset := offsets[0] + for i, o := range offsets { + dest[i] = o - startOffset + } + + default: + debug.Assert(arr.DataType().Layout().Buffers[1].ByteWidth == 4, "invalid offset bytewidth") + dest := arrow.Int32Traits.CastFromBytes(shiftedOffsets.Bytes()) + offsets := arrow.Int32Traits.CastFromBytes(voffsets.Bytes())[data.Offset() : data.Offset()+data.Len()+1] + + startOffset := offsets[0] + for i, o := range offsets { + dest[i] = o - startOffset + } + } + + voffsets = shiftedOffsets + } else { + voffsets.Retain() + } + + return voffsets +} + +// Truncates the offsets if needed and shifts the values if minOffset > 0. +// The offsets returned are corrected assuming the child values are truncated +// and now start at minOffset. +// +// This function only works on offset buffers of ListViews and LargeListViews. +// TODO(felipecrv): Unify this with getZeroBasedValueOffsets. +func (w *recordEncoder) getValueOffsetsAtBaseValue(arr arrow.Array, minOffset int) *memory.Buffer { + data := arr.Data() + voffsets := data.Buffers()[1] + offsetTraits := arr.DataType().(arrow.OffsetsDataType).OffsetTypeTraits() + offsetBytesNeeded := offsetTraits.BytesRequired(data.Len()) + + if voffsets == nil || voffsets.Len() == 0 { + return nil + } + + needsTruncate := data.Offset() != 0 || offsetBytesNeeded < voffsets.Len() + needsShift := minOffset > 0 + + if needsTruncate || needsShift { + shiftedOffsets := memory.NewResizableBuffer(w.mem) + shiftedOffsets.Resize(offsetBytesNeeded) + + switch arr.DataType().Layout().Buffers[1].ByteWidth { + case 8: + dest := arrow.Int64Traits.CastFromBytes(shiftedOffsets.Bytes()) + offsets := arrow.Int64Traits.CastFromBytes(voffsets.Bytes())[data.Offset() : data.Offset()+data.Len()] + + if minOffset > 0 { + for i, o := range offsets { + dest[i] = o - int64(minOffset) + } + } else { + copy(dest, offsets) + } + default: + debug.Assert(arr.DataType().Layout().Buffers[1].ByteWidth == 4, "invalid offset bytewidth") + dest := arrow.Int32Traits.CastFromBytes(shiftedOffsets.Bytes()) + offsets := arrow.Int32Traits.CastFromBytes(voffsets.Bytes())[data.Offset() : data.Offset()+data.Len()] + + if minOffset > 0 { + for i, o := range offsets { + dest[i] = o - int32(minOffset) + } + } else { + copy(dest, offsets) + } + } + + voffsets = shiftedOffsets + } else { + voffsets.Retain() + } + + return voffsets +} + +func (w *recordEncoder) rebaseDenseUnionValueOffsets(arr *array.DenseUnion, offsets, lengths []int32) *memory.Buffer { + // this case sucks. Because the offsets are different for each + // child array, when we have a sliced array, we need to re-base + // the value offsets for each array! ew. + unshiftedOffsets := arr.RawValueOffsets() + codes := arr.RawTypeCodes() + + shiftedOffsetsBuf := memory.NewResizableBuffer(w.mem) + shiftedOffsetsBuf.Resize(arrow.Int32Traits.BytesRequired(arr.Len())) + shiftedOffsets := arrow.Int32Traits.CastFromBytes(shiftedOffsetsBuf.Bytes()) + + // compute shifted offsets by subtracting child offset + for i, c := range codes { + if offsets[c] == -1 { + // offsets are guaranteed to be increasing according to the spec + // so the first offset we find for a child is the initial offset + // and will become the "0" for this child. + offsets[c] = unshiftedOffsets[i] + shiftedOffsets[i] = 0 + } else { + shiftedOffsets[i] = unshiftedOffsets[i] - offsets[c] + } + lengths[c] = maxI32(lengths[c], shiftedOffsets[i]+1) + } + return shiftedOffsetsBuf +} + +func (w *recordEncoder) Encode(p *Payload, rec arrow.Record) error { + if err := w.encode(p, rec); err != nil { + return err + } + return w.encodeMetadata(p, rec.NumRows()) +} + +func (w *recordEncoder) encodeMetadata(p *Payload, nrows int64) error { + p.meta = writeRecordMessage(w.mem, nrows, p.size, w.fields, w.meta, w.codec) + return nil +} + +func newTruncatedBitmap(mem memory.Allocator, offset, length int64, input *memory.Buffer) *memory.Buffer { + if input == nil { + return nil + } + + minLength := paddedLength(bitutil.BytesForBits(length), kArrowAlignment) + switch { + case offset != 0 || minLength < int64(input.Len()): + // with a sliced array / non-zero offset, we must copy the bitmap + buf := memory.NewResizableBuffer(mem) + buf.Resize(int(minLength)) + bitutil.CopyBitmap(input.Bytes(), int(offset), int(length), buf.Bytes(), 0) + return buf + default: + input.Retain() + return input + } +} + +func getTruncatedBuffer(offset, length int64, byteWidth int32, buf *memory.Buffer) *memory.Buffer { + if buf == nil { + return buf + } + + paddedLen := paddedLength(length*int64(byteWidth), kArrowAlignment) + if offset != 0 || paddedLen < int64(buf.Len()) { + return memory.SliceBuffer(buf, int(offset*int64(byteWidth)), int(minI64(paddedLen, int64(buf.Len())))) + } + buf.Retain() + return buf +} + +func needTruncate(offset int64, buf *memory.Buffer, minLength int64) bool { + if buf == nil { + return false + } + return offset != 0 || minLength < int64(buf.Len()) +} + +func minI64(a, b int64) int64 { + if a < b { + return a + } + return b +} + +func maxI32(a, b int32) int32 { + if a > b { + return a + } + return b +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/memory/Makefile b/vendor/github.com/apache/arrow/go/v14/arrow/memory/Makefile new file mode 100644 index 000000000..1cc4079c4 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/memory/Makefile @@ -0,0 +1,66 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +GO_BUILD=go build +GO_GEN=go generate +GO_TEST=go test +GOPATH=$(realpath ../../../..) + +# this converts rotate instructions from "ro[lr] " -> "ro[lr] , 1" for yasm compatibility +PERL_FIXUP_ROTATE=perl -i -pe 's/(ro[rl]\s+\w{2,3})$$/\1, 1/' + +C2GOASM=c2goasm -a -f +CC=clang +C_FLAGS=-target x86_64-unknown-none -masm=intel -mno-red-zone -mstackrealign -mllvm -inline-threshold=1000 -fno-asynchronous-unwind-tables \ + -fno-exceptions -fno-rtti -O3 -fno-builtin -ffast-math -fno-jump-tables -I_lib +ASM_FLAGS_AVX2=-mavx2 -mfma -mllvm -force-vector-width=32 +ASM_FLAGS_SSE3=-msse3 +ASM_FLAGS_SSE4=-msse4 + +C_FLAGS_NEON=-O3 -fvectorize -mllvm -force-vector-width=16 -fno-asynchronous-unwind-tables -mno-red-zone -mstackrealign -fno-exceptions \ + -fno-rtti -fno-builtin -ffast-math -fno-jump-tables -I_lib + +GO_SOURCES := $(shell find . -path ./_lib -prune -o -name '*.go' -not -name '*_test.go') +ALL_SOURCES := $(shell find . -path ./_lib -prune -o -name '*.go' -name '*.s' -not -name '*_test.go') + + +INTEL_SOURCES := \ + memory_avx2_amd64.s memory_sse4_amd64.s + +.PHONEY: assembly + +# +# ARROW-15320: DO NOT add the assembly target for Arm64 (ARM_SOURCES) until c2goasm added the Arm64 support. +# memory_neon_arm64.s were generated by asm2plan9s. +# And manually formatted it as the Arm64 Plan9. +# + +assembly: $(INTEL_SOURCES) + +_lib/memory_avx2.s: _lib/memory.c + $(CC) -S $(C_FLAGS) $(ASM_FLAGS_AVX2) $^ -o $@ ; $(PERL_FIXUP_ROTATE) $@ + +_lib/memory_sse4.s: _lib/memory.c + $(CC) -S $(C_FLAGS) $(ASM_FLAGS_SSE4) $^ -o $@ ; $(PERL_FIXUP_ROTATE) $@ + +_lib/memory_neon.s: _lib/memory.c + $(CC) -S $(C_FLAGS_NEON) $^ -o $@ ; $(PERL_FIXUP_ROTATE) $@ + +memory_avx2_amd64.s: _lib/memory_avx2.s + $(C2GOASM) -a -f $^ $@ + +memory_sse4_amd64.s: _lib/memory_sse4.s + $(C2GOASM) -a -f $^ $@ diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/memory/allocator.go b/vendor/github.com/apache/arrow/go/v14/arrow/memory/allocator.go new file mode 100644 index 000000000..1427190ea --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/memory/allocator.go @@ -0,0 +1,27 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package memory + +const ( + alignment = 64 +) + +type Allocator interface { + Allocate(size int) []byte + Reallocate(size int, b []byte) []byte + Free(b []byte) +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/memory/buffer.go b/vendor/github.com/apache/arrow/go/v14/arrow/memory/buffer.go new file mode 100644 index 000000000..2ddb3f829 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/memory/buffer.go @@ -0,0 +1,145 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package memory + +import ( + "sync/atomic" + + "github.com/apache/arrow/go/v14/arrow/internal/debug" +) + +// Buffer is a wrapper type for a buffer of bytes. +type Buffer struct { + refCount int64 + buf []byte + length int + mutable bool + mem Allocator + + parent *Buffer +} + +// NewBufferBytes creates a fixed-size buffer from the specified data. +func NewBufferBytes(data []byte) *Buffer { + return &Buffer{refCount: 0, buf: data, length: len(data)} +} + +// NewResizableBuffer creates a mutable, resizable buffer with an Allocator for managing memory. +func NewResizableBuffer(mem Allocator) *Buffer { + return &Buffer{refCount: 1, mutable: true, mem: mem} +} + +func SliceBuffer(buf *Buffer, offset, length int) *Buffer { + buf.Retain() + return &Buffer{refCount: 1, parent: buf, buf: buf.Bytes()[offset : offset+length], length: length} +} + +// Parent returns either nil or a pointer to the parent buffer if this buffer +// was sliced from another. +func (b *Buffer) Parent() *Buffer { return b.parent } + +// Retain increases the reference count by 1. +func (b *Buffer) Retain() { + if b.mem != nil || b.parent != nil { + atomic.AddInt64(&b.refCount, 1) + } +} + +// Release decreases the reference count by 1. +// When the reference count goes to zero, the memory is freed. +func (b *Buffer) Release() { + if b.mem != nil || b.parent != nil { + debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases") + + if atomic.AddInt64(&b.refCount, -1) == 0 { + if b.mem != nil { + b.mem.Free(b.buf) + } else { + b.parent.Release() + b.parent = nil + } + b.buf, b.length = nil, 0 + } + } +} + +// Reset resets the buffer for reuse. +func (b *Buffer) Reset(buf []byte) { + if b.parent != nil { + b.parent.Release() + b.parent = nil + } + b.buf = buf + b.length = len(buf) +} + +// Buf returns the slice of memory allocated by the Buffer, which is adjusted by calling Reserve. +func (b *Buffer) Buf() []byte { return b.buf } + +// Bytes returns a slice of size Len, which is adjusted by calling Resize. +func (b *Buffer) Bytes() []byte { return b.buf[:b.length] } + +// Mutable returns a bool indicating whether the buffer is mutable or not. +func (b *Buffer) Mutable() bool { return b.mutable } + +// Len returns the length of the buffer. +func (b *Buffer) Len() int { return b.length } + +// Cap returns the capacity of the buffer. +func (b *Buffer) Cap() int { return len(b.buf) } + +// Reserve reserves the provided amount of capacity for the buffer. +func (b *Buffer) Reserve(capacity int) { + if capacity > len(b.buf) { + newCap := roundUpToMultipleOf64(capacity) + if len(b.buf) == 0 { + b.buf = b.mem.Allocate(newCap) + } else { + b.buf = b.mem.Reallocate(newCap, b.buf) + } + } +} + +// Resize resizes the buffer to the target size. +func (b *Buffer) Resize(newSize int) { + b.resize(newSize, true) +} + +// ResizeNoShrink resizes the buffer to the target size, but will not +// shrink it. +func (b *Buffer) ResizeNoShrink(newSize int) { + b.resize(newSize, false) +} + +func (b *Buffer) resize(newSize int, shrink bool) { + if !shrink || newSize > b.length { + b.Reserve(newSize) + } else { + // Buffer is not growing, so shrink to the requested size without + // excess space. + newCap := roundUpToMultipleOf64(newSize) + if len(b.buf) != newCap { + if newSize == 0 { + b.mem.Free(b.buf) + b.buf = nil + } else { + b.buf = b.mem.Reallocate(newCap, b.buf) + } + } + } + b.length = newSize +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/memory/cgo_allocator.go b/vendor/github.com/apache/arrow/go/v14/arrow/memory/cgo_allocator.go new file mode 100644 index 000000000..85ee44521 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/memory/cgo_allocator.go @@ -0,0 +1,108 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build cgo +// +build ccalloc + +package memory + +import ( + "runtime" + + cga "github.com/apache/arrow/go/v14/arrow/memory/internal/cgoalloc" +) + +// CgoArrowAllocator is an allocator which exposes the C++ memory pool class +// from the Arrow C++ Library as an allocator for memory buffers to use in Go. +// The build tag 'ccalloc' must be used in order to include it as it requires +// linking against the arrow library. +// +// The primary reason to use this would be as an allocator when dealing with +// exporting data across the cdata interface in order to ensure that the memory +// is allocated safely on the C side so it can be held on the CGO side beyond +// the context of a single function call. If the memory in use isn't allocated +// on the C side, then it is not safe for any pointers to data to be held outside +// of Go beyond the context of a single Cgo function call as it will be invisible +// to the Go garbage collector and could potentially get moved without being updated. +// +// As an alternative, if the arrow C++ libraries aren't available, remember that +// Allocator is an interface, so anything which can allocate data using C/C++ can +// be exposed and then used to meet the Allocator interface if wanting to export data +// across the Cgo interfaces. +type CgoArrowAllocator struct { + pool cga.CGOMemPool +} + +// Allocate does what it says on the tin, allocates a chunk of memory using the underlying +// memory pool, however CGO calls are 'relatively' expensive, which means doing tons of +// small allocations can end up being expensive and potentially slower than just using +// go memory. This means that preallocating via reserve becomes much more important when +// using this allocator. +// +// Future development TODO: look into converting this more into a slab style allocator +// which amortizes the cost of smaller allocations by allocating bigger chunks of memory +// and passes them out. +func (alloc *CgoArrowAllocator) Allocate(size int) []byte { + b := cga.CgoPoolAlloc(alloc.pool, size) + return b +} + +func (alloc *CgoArrowAllocator) Free(b []byte) { + cga.CgoPoolFree(alloc.pool, b) +} + +func (alloc *CgoArrowAllocator) Reallocate(size int, b []byte) []byte { + oldSize := len(b) + out := cga.CgoPoolRealloc(alloc.pool, size, b) + + if size > oldSize { + // zero initialize the slice like go would do normally + // C won't zero initialize the memory. + Set(out[oldSize:], 0) + } + return out +} + +// AllocatedBytes returns the current total of bytes that have been allocated by +// the memory pool on the C++ side. +func (alloc *CgoArrowAllocator) AllocatedBytes() int64 { + return cga.CgoPoolCurBytes(alloc.pool) +} + +// AssertSize can be used for testing to ensure and check that there are no memory +// leaks using the allocator. +func (alloc *CgoArrowAllocator) AssertSize(t TestingT, sz int) { + cur := alloc.AllocatedBytes() + if int64(sz) != cur { + t.Helper() + t.Errorf("invalid memory size exp=%d, got=%d", sz, cur) + } +} + +// NewCgoArrowAllocator creates a new allocator which is backed by the C++ Arrow +// memory pool object which could potentially be using jemalloc or mimalloc or +// otherwise as its backend. Memory allocated by this is invisible to the Go +// garbage collector, and as such care should be taken to avoid any memory leaks. +// +// A finalizer is set on the allocator so when the allocator object itself is eventually +// cleaned up by the garbage collector, it will delete the associated C++ memory pool +// object. If the build tag 'cclog' is added, then the memory pool will output a log line +// for every time memory is allocated, freed or reallocated. +func NewCgoArrowAllocator() *CgoArrowAllocator { + alloc := &CgoArrowAllocator{pool: cga.NewCgoArrowAllocator(enableLogging)} + runtime.SetFinalizer(alloc, func(a *CgoArrowAllocator) { cga.ReleaseCGOMemPool(a.pool) }) + return alloc +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/memory/cgo_allocator_defaults.go b/vendor/github.com/apache/arrow/go/v14/arrow/memory/cgo_allocator_defaults.go new file mode 100644 index 000000000..501431a0e --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/memory/cgo_allocator_defaults.go @@ -0,0 +1,23 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build cgo +// +build ccalloc +// +build !cclog + +package memory + +const enableLogging = false diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/memory/cgo_allocator_logging.go b/vendor/github.com/apache/arrow/go/v14/arrow/memory/cgo_allocator_logging.go new file mode 100644 index 000000000..01ad6b394 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/memory/cgo_allocator_logging.go @@ -0,0 +1,23 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build cgo +// +build ccalloc +// +build cclog + +package memory + +const enableLogging = true diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/memory/checked_allocator.go b/vendor/github.com/apache/arrow/go/v14/arrow/memory/checked_allocator.go new file mode 100644 index 000000000..78a09a57d --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/memory/checked_allocator.go @@ -0,0 +1,221 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !tinygo +// +build !tinygo + +package memory + +import ( + "fmt" + "os" + "runtime" + "strconv" + "strings" + "sync" + "sync/atomic" + "unsafe" +) + +type CheckedAllocator struct { + mem Allocator + sz int64 + + allocs sync.Map +} + +func NewCheckedAllocator(mem Allocator) *CheckedAllocator { + return &CheckedAllocator{mem: mem} +} + +func (a *CheckedAllocator) CurrentAlloc() int { return int(atomic.LoadInt64(&a.sz)) } + +func (a *CheckedAllocator) Allocate(size int) []byte { + atomic.AddInt64(&a.sz, int64(size)) + out := a.mem.Allocate(size) + if size == 0 { + return out + } + + ptr := uintptr(unsafe.Pointer(&out[0])) + pcs := make([]uintptr, maxRetainedFrames) + + // For historical reasons the meaning of the skip argument + // differs between Caller and Callers. For Callers, 0 identifies + // the frame for the caller itself. We skip 2 additional frames + // here to get to the caller right before the call to Allocate. + runtime.Callers(allocFrames+2, pcs) + callersFrames := runtime.CallersFrames(pcs) + if pc, _, l, ok := runtime.Caller(allocFrames); ok { + a.allocs.Store(ptr, &dalloc{pc: pc, line: l, sz: size, callersFrames: callersFrames}) + } + return out +} + +func (a *CheckedAllocator) Reallocate(size int, b []byte) []byte { + atomic.AddInt64(&a.sz, int64(size-len(b))) + + oldptr := uintptr(unsafe.Pointer(&b[0])) + out := a.mem.Reallocate(size, b) + if size == 0 { + return out + } + + newptr := uintptr(unsafe.Pointer(&out[0])) + a.allocs.Delete(oldptr) + pcs := make([]uintptr, maxRetainedFrames) + + // For historical reasons the meaning of the skip argument + // differs between Caller and Callers. For Callers, 0 identifies + // the frame for the caller itself. We skip 2 additional frames + // here to get to the caller right before the call to Reallocate. + runtime.Callers(reallocFrames+2, pcs) + callersFrames := runtime.CallersFrames(pcs) + if pc, _, l, ok := runtime.Caller(reallocFrames); ok { + a.allocs.Store(newptr, &dalloc{pc: pc, line: l, sz: size, callersFrames: callersFrames}) + } + + return out +} + +func (a *CheckedAllocator) Free(b []byte) { + atomic.AddInt64(&a.sz, int64(len(b)*-1)) + defer a.mem.Free(b) + + if len(b) == 0 { + return + } + + ptr := uintptr(unsafe.Pointer(&b[0])) + a.allocs.Delete(ptr) +} + +// typically the allocations are happening in memory.Buffer, not by consumers calling +// allocate/reallocate directly. As a result, we want to skip the caller frames +// of the inner workings of Buffer in order to find the caller that actually triggered +// the allocation via a call to Resize/Reserve/etc. +const ( + defAllocFrames = 4 + defReallocFrames = 3 + defMaxRetainedFrames = 0 +) + +// Use the environment variables ARROW_CHECKED_ALLOC_FRAMES and ARROW_CHECKED_REALLOC_FRAMES +// to control how many frames it skips when storing the caller for allocations/reallocs +// when using this to find memory leaks. Use ARROW_CHECKED_MAX_RETAINED_FRAMES to control how +// many frames are retained for printing the stack trace of a leak. +var allocFrames, reallocFrames, maxRetainedFrames int = defAllocFrames, defReallocFrames, defMaxRetainedFrames + +func init() { + if val, ok := os.LookupEnv("ARROW_CHECKED_ALLOC_FRAMES"); ok { + if f, err := strconv.Atoi(val); err == nil { + allocFrames = f + } + } + + if val, ok := os.LookupEnv("ARROW_CHECKED_REALLOC_FRAMES"); ok { + if f, err := strconv.Atoi(val); err == nil { + reallocFrames = f + } + } + + if val, ok := os.LookupEnv("ARROW_CHECKED_MAX_RETAINED_FRAMES"); ok { + if f, err := strconv.Atoi(val); err == nil { + maxRetainedFrames = f + } + } +} + +type dalloc struct { + pc uintptr + line int + sz int + callersFrames *runtime.Frames +} + +type TestingT interface { + Errorf(format string, args ...interface{}) + Helper() +} + +func (a *CheckedAllocator) AssertSize(t TestingT, sz int) { + a.allocs.Range(func(_, value interface{}) bool { + info := value.(*dalloc) + f := runtime.FuncForPC(info.pc) + frames := info.callersFrames + var callersMsg strings.Builder + for { + frame, more := frames.Next() + if frame.Line == 0 { + break + } + callersMsg.WriteString("\t") + // frame.Func is a useful source of information if it's present. + // It may be nil for non-Go code or fully inlined functions. + if fn := frame.Func; fn != nil { + // format as func name + the offset in bytes from func entrypoint + callersMsg.WriteString(fmt.Sprintf("%s+%x", fn.Name(), frame.PC-fn.Entry())) + } else { + // fallback to outer func name + file line + callersMsg.WriteString(fmt.Sprintf("%s, line %d", frame.Function, frame.Line)) + } + + // Write a proper file name + line, so it's really easy to find the leak + callersMsg.WriteString("\n\t\t") + callersMsg.WriteString(frame.File + ":" + strconv.Itoa(frame.Line)) + callersMsg.WriteString("\n") + if !more { + break + } + } + + file, line := f.FileLine(info.pc) + t.Errorf("LEAK of %d bytes FROM\n\t%s+%x\n\t\t%s:%d\n%v", + info.sz, + f.Name(), info.pc-f.Entry(), // func name + offset in bytes between frame & entrypoint to func + file, line, // a proper file name + line, so it's really easy to find the leak + callersMsg.String(), + ) + return true + }) + + if int(atomic.LoadInt64(&a.sz)) != sz { + t.Helper() + t.Errorf("invalid memory size exp=%d, got=%d", sz, a.sz) + } +} + +type CheckedAllocatorScope struct { + alloc *CheckedAllocator + sz int +} + +func NewCheckedAllocatorScope(alloc *CheckedAllocator) *CheckedAllocatorScope { + sz := atomic.LoadInt64(&alloc.sz) + return &CheckedAllocatorScope{alloc: alloc, sz: int(sz)} +} + +func (c *CheckedAllocatorScope) CheckSize(t TestingT) { + sz := int(atomic.LoadInt64(&c.alloc.sz)) + if c.sz != sz { + t.Helper() + t.Errorf("invalid memory size exp=%d, got=%d", c.sz, sz) + } +} + +var ( + _ Allocator = (*CheckedAllocator)(nil) +) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/memory/default_allocator.go b/vendor/github.com/apache/arrow/go/v14/arrow/memory/default_allocator.go new file mode 100644 index 000000000..f60caccdb --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/memory/default_allocator.go @@ -0,0 +1,25 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !mallocator || !cgo + +package memory + +// DefaultAllocator is a default implementation of Allocator and can be used anywhere +// an Allocator is required. +// +// DefaultAllocator is safe to use from multiple goroutines. +var DefaultAllocator Allocator = NewGoAllocator() diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/memory/default_mallocator.go b/vendor/github.com/apache/arrow/go/v14/arrow/memory/default_mallocator.go new file mode 100644 index 000000000..12ad08466 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/memory/default_mallocator.go @@ -0,0 +1,29 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build mallocator && cgo + +package memory + +import ( + "github.com/apache/arrow/go/v14/arrow/memory/mallocator" +) + +// DefaultAllocator is a default implementation of Allocator and can be used anywhere +// an Allocator is required. +// +// DefaultAllocator is safe to use from multiple goroutines. +var DefaultAllocator Allocator = mallocator.NewMallocator() diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/memory/doc.go b/vendor/github.com/apache/arrow/go/v14/arrow/memory/doc.go new file mode 100644 index 000000000..20a28e4e2 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/memory/doc.go @@ -0,0 +1,22 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/* +Package memory provides support for allocating and manipulating memory at a low level. + +The build tag 'mallocator' will switch the default allocator to one backed by libc malloc. This also requires CGO. +*/ +package memory diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/memory/go_allocator.go b/vendor/github.com/apache/arrow/go/v14/arrow/memory/go_allocator.go new file mode 100644 index 000000000..1017eb688 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/memory/go_allocator.go @@ -0,0 +1,47 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package memory + +type GoAllocator struct{} + +func NewGoAllocator() *GoAllocator { return &GoAllocator{} } + +func (a *GoAllocator) Allocate(size int) []byte { + buf := make([]byte, size+alignment) // padding for 64-byte alignment + addr := int(addressOf(buf)) + next := roundUpToMultipleOf64(addr) + if addr != next { + shift := next - addr + return buf[shift : size+shift : size+shift] + } + return buf[:size:size] +} + +func (a *GoAllocator) Reallocate(size int, b []byte) []byte { + if cap(b) >= size { + return b[:size] + } + newBuf := a.Allocate(size) + copy(newBuf, b) + return newBuf +} + +func (a *GoAllocator) Free(b []byte) {} + +var ( + _ Allocator = (*GoAllocator)(nil) +) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/memory/internal/cgoalloc/allocator.cc b/vendor/github.com/apache/arrow/go/v14/arrow/memory/internal/cgoalloc/allocator.cc new file mode 100644 index 000000000..b2b037374 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/memory/internal/cgoalloc/allocator.cc @@ -0,0 +1,71 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +// +build ccalloc + +#include "allocator.h" +#include "arrow/memory_pool.h" +#include "helpers.h" + +struct mem_holder { + std::unique_ptr owned_pool; + arrow::MemoryPool* pool; +}; + +ArrowMemoryPool arrow_create_memory_pool(bool enable_logging) { + auto holder = std::make_shared(); + if (enable_logging) { + holder->owned_pool.reset(new arrow::LoggingMemoryPool(arrow::default_memory_pool())); + holder->pool = holder->owned_pool.get(); + } else { + holder->pool = arrow::default_memory_pool(); + } + + return create_ref(holder); +} + +void arrow_release_pool(ArrowMemoryPool pool) { + release_ref(pool); +} + +int arrow_pool_allocate(ArrowMemoryPool pool, int64_t size, uint8_t** out) { + auto holder = retrieve_instance(pool); + auto status = holder->pool->Allocate(size, out); + if (!status.ok()) { + return 1; + } + return 0; +} + +void arrow_pool_free(ArrowMemoryPool pool, uint8_t* buffer, int64_t size) { + auto holder = retrieve_instance(pool); + holder->pool->Free(buffer, size); +} + +int arrow_pool_reallocate(ArrowMemoryPool pool, int64_t old_size, int64_t new_size, uint8_t** ptr) { + auto holder = retrieve_instance(pool); + auto status = holder->pool->Reallocate(old_size, new_size, ptr); + if (!status.ok()) { + return 1; + } + return 0; +} + +int64_t arrow_pool_bytes_allocated(ArrowMemoryPool pool) { + auto holder = retrieve_instance(pool); + return holder->pool->bytes_allocated(); +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/memory/internal/cgoalloc/allocator.go b/vendor/github.com/apache/arrow/go/v14/arrow/memory/internal/cgoalloc/allocator.go new file mode 100644 index 000000000..48f34d862 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/memory/internal/cgoalloc/allocator.go @@ -0,0 +1,108 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build ccalloc +// +build ccalloc + +package cgoalloc + +// #cgo !windows pkg-config: arrow +// #cgo CXXFLAGS: -std=c++17 +// #cgo windows LDFLAGS: -larrow +// #include "allocator.h" +import "C" +import ( + "reflect" + "unsafe" +) + +// CGOMemPool is an alias to the typedef'd uintptr from the allocator.h file +type CGOMemPool = C.ArrowMemoryPool + +// CgoPoolAlloc allocates a block of memory of length 'size' using the memory +// pool that is passed in. +func CgoPoolAlloc(pool CGOMemPool, size int) []byte { + var ret []byte + if size == 0 { + return ret + } + + var out *C.uint8_t + C.arrow_pool_allocate(pool, C.int64_t(size), (**C.uint8_t)(unsafe.Pointer(&out))) + + s := (*reflect.SliceHeader)(unsafe.Pointer(&ret)) + s.Data = uintptr(unsafe.Pointer(out)) + s.Len = size + s.Cap = size + + return ret +} + +// CgoPoolRealloc calls 'reallocate' on the block of memory passed in which must +// be a slice that was returned by CgoPoolAlloc or CgoPoolRealloc. +func CgoPoolRealloc(pool CGOMemPool, size int, b []byte) []byte { + if len(b) == 0 { + return CgoPoolAlloc(pool, size) + } + + oldSize := C.int64_t(len(b)) + data := (*C.uint8_t)(unsafe.Pointer(&b[0])) + C.arrow_pool_reallocate(pool, oldSize, C.int64_t(size), &data) + + var ret []byte + s := (*reflect.SliceHeader)(unsafe.Pointer(&ret)) + s.Data = uintptr(unsafe.Pointer(data)) + s.Len = size + s.Cap = size + + return ret +} + +// CgoPoolFree uses the indicated memory pool to free a block of memory. The +// slice passed in *must* be a slice which was returned by CgoPoolAlloc or +// CgoPoolRealloc. +func CgoPoolFree(pool CGOMemPool, b []byte) { + if len(b) == 0 { + return + } + + oldSize := C.int64_t(len(b)) + data := (*C.uint8_t)(unsafe.Pointer(&b[0])) + C.arrow_pool_free(pool, data, oldSize) +} + +// CgoPoolCurBytes returns the current number of bytes allocated by the +// passed in memory pool. +func CgoPoolCurBytes(pool CGOMemPool) int64 { + return int64(C.arrow_pool_bytes_allocated(pool)) +} + +// ReleaseCGOMemPool deletes and frees the memory associated with the +// passed in memory pool on the C++ side. +func ReleaseCGOMemPool(pool CGOMemPool) { + C.arrow_release_pool(pool) +} + +// NewCgoArrowAllocator constructs a new memory pool in C++ and returns +// a reference to it which can then be used with the other functions +// here in order to use it. +// +// Optionally if logging is true, a logging proxy will be wrapped around +// the memory pool so that it will output a line every time memory is +// allocated, reallocated or freed along with the size of the allocation. +func NewCgoArrowAllocator(logging bool) CGOMemPool { + return C.arrow_create_memory_pool(C.bool(logging)) +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/memory/internal/cgoalloc/allocator.h b/vendor/github.com/apache/arrow/go/v14/arrow/memory/internal/cgoalloc/allocator.h new file mode 100644 index 000000000..0c8744375 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/memory/internal/cgoalloc/allocator.h @@ -0,0 +1,39 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef uintptr_t ArrowMemoryPool; + +ArrowMemoryPool arrow_create_memory_pool(bool enable_logging); +int arrow_pool_allocate(ArrowMemoryPool pool, int64_t size, uint8_t** out); +int arrow_pool_reallocate(ArrowMemoryPool pool, int64_t old_size, int64_t new_size, uint8_t** ptr); +void arrow_pool_free(ArrowMemoryPool pool, uint8_t* buffer, int64_t size); +int64_t arrow_pool_bytes_allocated(ArrowMemoryPool pool); +void arrow_release_pool(ArrowMemoryPool pool); + + +#ifdef __cplusplus +} +#endif diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/memory/internal/cgoalloc/helpers.h b/vendor/github.com/apache/arrow/go/v14/arrow/memory/internal/cgoalloc/helpers.h new file mode 100644 index 000000000..fa5feb6a9 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/memory/internal/cgoalloc/helpers.h @@ -0,0 +1,52 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#pragma once + +#include +#include + +// helper functions to be included by C++ code for interacting with Cgo + +// create_ref will construct a shared_ptr on the heap and return a pointer +// to it. the returned uintptr_t can then be used with retrieve_instance +// to get back the shared_ptr and object it refers to. This ensures that +// the object outlives the exported function so that Go can use it. +template +uintptr_t create_ref(std::shared_ptr t) { + std::shared_ptr* retained_ptr = new std::shared_ptr(t); + return reinterpret_cast(retained_ptr); +} + +// retrieve_instance is used to get back the shared_ptr which was created with +// create_ref in order to use it in functions where the caller passes back the +// uintptr_t so that an object can be managed by C++ while a reference to it +// is passed around in C/CGO +template +std::shared_ptr retrieve_instance(uintptr_t ref) { + std::shared_ptr* retrieved_ptr = reinterpret_cast*>(ref); + return *retrieved_ptr; +} + +// release_ref deletes the shared_ptr that was created by create_ref, freeing the +// object if it was the last shared_ptr which referenced it as per normal smart_ptr +// rules. +template +void release_ref(uintptr_t ref) { + std::shared_ptr* retrieved_ptr = reinterpret_cast*>(ref); + delete retrieved_ptr; +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/memory/mallocator/doc.go b/vendor/github.com/apache/arrow/go/v14/arrow/memory/mallocator/doc.go new file mode 100644 index 000000000..a399d85ee --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/memory/mallocator/doc.go @@ -0,0 +1,21 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +// Package mallocator defines an allocator implementation for +// memory.Allocator which defers to libc malloc. It requires +// usage of CGO. +package mallocator diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/memory/mallocator/mallocator.go b/vendor/github.com/apache/arrow/go/v14/arrow/memory/mallocator/mallocator.go new file mode 100644 index 000000000..18e0377c4 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/memory/mallocator/mallocator.go @@ -0,0 +1,115 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package mallocator + +// #include +// #include +// +// void* realloc_and_initialize(void* ptr, size_t old_len, size_t new_len) { +// void* new_ptr = realloc(ptr, new_len); +// if (new_ptr && new_len > old_len) { +// memset(new_ptr + old_len, 0, new_len - old_len); +// } +// return new_ptr; +// } +import "C" + +import ( + "reflect" + "sync/atomic" + "unsafe" +) + +// Mallocator is an allocator which defers to libc malloc. +// +// The priamry reason to use this is when exporting data across the C Data +// Interface. CGO requires that pointers to Go memory are not stored in C +// memory, which is exactly what the C Data Interface would otherwise +// require. By allocating with Mallocator up front, we can safely export the +// buffers in Arrow arrays without copying buffers or violating CGO rules. +// +// The build tag 'mallocator' will also make this the default allocator. +type Mallocator struct { + allocatedBytes uint64 +} + +func NewMallocator() *Mallocator { return &Mallocator{} } + +func (alloc *Mallocator) Allocate(size int) []byte { + // Use calloc to zero-initialize memory. + // > ...the current implementation may sometimes cause a runtime error if the + // > contents of the C memory appear to be a Go pointer. Therefore, avoid + // > passing uninitialized C memory to Go code if the Go code is going to store + // > pointer values in it. Zero out the memory in C before passing it to Go. + if size < 0 { + panic("mallocator: negative size") + } + ptr, err := C.calloc(C.size_t(size), 1) + if err != nil { + panic(err) + } else if ptr == nil { + panic("mallocator: out of memory") + } + atomic.AddUint64(&alloc.allocatedBytes, uint64(size)) + return unsafe.Slice((*byte)(ptr), size) +} + +func (alloc *Mallocator) Free(b []byte) { + sh := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + C.free(unsafe.Pointer(sh.Data)) + // Subtract sh.Len via two's complement (since atomic doesn't offer subtract) + atomic.AddUint64(&alloc.allocatedBytes, ^(uint64(sh.Len) - 1)) +} + +func (alloc *Mallocator) Reallocate(size int, b []byte) []byte { + if size < 0 { + panic("mallocator: negative size") + } + sh := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + ptr, err := C.realloc_and_initialize(unsafe.Pointer(sh.Data), C.size_t(sh.Cap), C.size_t(size)) + if err != nil { + panic(err) + } else if ptr == nil && size != 0 { + panic("mallocator: out of memory") + } + delta := size - len(b) + if delta >= 0 { + atomic.AddUint64(&alloc.allocatedBytes, uint64(delta)) + } else { + atomic.AddUint64(&alloc.allocatedBytes, ^(uint64(-delta) - 1)) + } + return unsafe.Slice((*byte)(ptr), size) +} + +func (alloc *Mallocator) AllocatedBytes() int64 { + return int64(alloc.allocatedBytes) +} + +// Duplicate interface to avoid circular import +type TestingT interface { + Errorf(format string, args ...interface{}) + Helper() +} + +func (alloc *Mallocator) AssertSize(t TestingT, sz int) { + cur := alloc.AllocatedBytes() + if int64(sz) != cur { + t.Helper() + t.Errorf("invalid memory size exp=%d, got=%d", sz, cur) + } +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/memory/memory.go b/vendor/github.com/apache/arrow/go/v14/arrow/memory/memory.go new file mode 100644 index 000000000..43627f5ed --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/memory/memory.go @@ -0,0 +1,33 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package memory + +var ( + memset func(b []byte, c byte) = memory_memset_go +) + +// Set assigns the value c to every element of the slice buf. +func Set(buf []byte, c byte) { + memset(buf, c) +} + +// memory_memset_go reference implementation +func memory_memset_go(buf []byte, c byte) { + for i := 0; i < len(buf); i++ { + buf[i] = c + } +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/memory/memory_amd64.go b/vendor/github.com/apache/arrow/go/v14/arrow/memory/memory_amd64.go new file mode 100644 index 000000000..58356d648 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/memory/memory_amd64.go @@ -0,0 +1,33 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build !noasm + +package memory + +import ( + "golang.org/x/sys/cpu" +) + +func init() { + if cpu.X86.HasAVX2 { + memset = memory_memset_avx2 + } else if cpu.X86.HasSSE42 { + memset = memory_memset_sse4 + } else { + memset = memory_memset_go + } +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/memory/memory_arm64.go b/vendor/github.com/apache/arrow/go/v14/arrow/memory/memory_arm64.go new file mode 100644 index 000000000..3db5d1101 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/memory/memory_arm64.go @@ -0,0 +1,31 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build !noasm + +package memory + +import ( + "golang.org/x/sys/cpu" +) + +func init() { + if cpu.ARM64.HasASIMD { + memset = memory_memset_neon + } else { + memset = memory_memset_go + } +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/memory/memory_avx2_amd64.go b/vendor/github.com/apache/arrow/go/v14/arrow/memory/memory_avx2_amd64.go new file mode 100644 index 000000000..2bd851ea5 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/memory/memory_avx2_amd64.go @@ -0,0 +1,41 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build !noasm + +package memory + +import "unsafe" + +//go:noescape +func _memset_avx2(buf unsafe.Pointer, len, c uintptr) + +func memory_memset_avx2(buf []byte, c byte) { + if len(buf) == 0 { + return + } + + var ( + p1 = unsafe.Pointer(&buf[0]) + p2 = uintptr(len(buf)) + p3 = uintptr(c) + ) + if len(buf) > 2000 || isMultipleOfPowerOf2(len(buf), 256) { + _memset_avx2(p1, p2, p3) + } else { + _memset_sse4(p1, p2, p3) + } +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/memory/memory_avx2_amd64.s b/vendor/github.com/apache/arrow/go/v14/arrow/memory/memory_avx2_amd64.s new file mode 100644 index 000000000..2a77807cb --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/memory/memory_avx2_amd64.s @@ -0,0 +1,85 @@ +//+build !noasm !appengine +// AUTO-GENERATED BY C2GOASM -- DO NOT EDIT + +TEXT ·_memset_avx2(SB), $0-24 + + MOVQ buf+0(FP), DI + MOVQ len+8(FP), SI + MOVQ c+16(FP), DX + + LONG $0x371c8d4c // lea r11, [rdi + rsi] + WORD $0x3949; BYTE $0xfb // cmp r11, rdi + JBE LBB0_13 + LONG $0x80fe8148; WORD $0x0000; BYTE $0x00 // cmp rsi, 128 + JB LBB0_12 + WORD $0x8949; BYTE $0xf0 // mov r8, rsi + LONG $0x80e08349 // and r8, -128 + WORD $0x8949; BYTE $0xf2 // mov r10, rsi + LONG $0x80e28349 // and r10, -128 + JE LBB0_12 + LONG $0xc26ef9c5 // vmovd xmm0, edx + LONG $0x787de2c4; BYTE $0xc0 // vpbroadcastb ymm0, xmm0 + LONG $0x804a8d4d // lea r9, [r10 - 128] + WORD $0x8944; BYTE $0xc8 // mov eax, r9d + WORD $0xe8c1; BYTE $0x07 // shr eax, 7 + WORD $0xc0ff // inc eax + LONG $0x03e08348 // and rax, 3 + JE LBB0_4 + WORD $0xf748; BYTE $0xd8 // neg rax + WORD $0xc931 // xor ecx, ecx + +LBB0_6: + LONG $0x047ffec5; BYTE $0x0f // vmovdqu yword [rdi + rcx], ymm0 + LONG $0x447ffec5; WORD $0x200f // vmovdqu yword [rdi + rcx + 32], ymm0 + LONG $0x447ffec5; WORD $0x400f // vmovdqu yword [rdi + rcx + 64], ymm0 + LONG $0x447ffec5; WORD $0x600f // vmovdqu yword [rdi + rcx + 96], ymm0 + LONG $0x80e98348 // sub rcx, -128 + WORD $0xff48; BYTE $0xc0 // inc rax + JNE LBB0_6 + JMP LBB0_7 + +LBB0_4: + WORD $0xc931 // xor ecx, ecx + +LBB0_7: + LONG $0x80f98149; WORD $0x0001; BYTE $0x00 // cmp r9, 384 + JB LBB0_10 + WORD $0x894c; BYTE $0xd0 // mov rax, r10 + WORD $0x2948; BYTE $0xc8 // sub rax, rcx + QUAD $0x000001e00f8c8d48 // lea rcx, [rdi + rcx + 480] + +LBB0_9: + QUAD $0xfffffe20817ffec5 // vmovdqu yword [rcx - 480], ymm0 + QUAD $0xfffffe40817ffec5 // vmovdqu yword [rcx - 448], ymm0 + QUAD $0xfffffe60817ffec5 // vmovdqu yword [rcx - 416], ymm0 + QUAD $0xfffffe80817ffec5 // vmovdqu yword [rcx - 384], ymm0 + QUAD $0xfffffea0817ffec5 // vmovdqu yword [rcx - 352], ymm0 + QUAD $0xfffffec0817ffec5 // vmovdqu yword [rcx - 320], ymm0 + QUAD $0xfffffee0817ffec5 // vmovdqu yword [rcx - 288], ymm0 + QUAD $0xffffff00817ffec5 // vmovdqu yword [rcx - 256], ymm0 + QUAD $0xffffff20817ffec5 // vmovdqu yword [rcx - 224], ymm0 + QUAD $0xffffff40817ffec5 // vmovdqu yword [rcx - 192], ymm0 + QUAD $0xffffff60817ffec5 // vmovdqu yword [rcx - 160], ymm0 + LONG $0x417ffec5; BYTE $0x80 // vmovdqu yword [rcx - 128], ymm0 + LONG $0x417ffec5; BYTE $0xa0 // vmovdqu yword [rcx - 96], ymm0 + LONG $0x417ffec5; BYTE $0xc0 // vmovdqu yword [rcx - 64], ymm0 + LONG $0x417ffec5; BYTE $0xe0 // vmovdqu yword [rcx - 32], ymm0 + LONG $0x017ffec5 // vmovdqu yword [rcx], ymm0 + LONG $0x00c18148; WORD $0x0002; BYTE $0x00 // add rcx, 512 + LONG $0xfe000548; WORD $0xffff // add rax, -512 + JNE LBB0_9 + +LBB0_10: + WORD $0x3949; BYTE $0xf2 // cmp r10, rsi + JE LBB0_13 + WORD $0x014c; BYTE $0xc7 // add rdi, r8 + +LBB0_12: + WORD $0x1788 // mov byte [rdi], dl + WORD $0xff48; BYTE $0xc7 // inc rdi + WORD $0x3949; BYTE $0xfb // cmp r11, rdi + JNE LBB0_12 + +LBB0_13: + VZEROUPPER + RET diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/memory/memory_js_wasm.go b/vendor/github.com/apache/arrow/go/v14/arrow/memory/memory_js_wasm.go new file mode 100644 index 000000000..9b94d99ff --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/memory/memory_js_wasm.go @@ -0,0 +1,23 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build wasm + +package memory + +func init() { + memset = memory_memset_go +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/memory/memory_neon_arm64.go b/vendor/github.com/apache/arrow/go/v14/arrow/memory/memory_neon_arm64.go new file mode 100644 index 000000000..6cb0400c9 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/memory/memory_neon_arm64.go @@ -0,0 +1,31 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build !noasm + +package memory + +import "unsafe" + +//go:noescape +func _memset_neon(buf unsafe.Pointer, len, c uintptr) + +func memory_memset_neon(buf []byte, c byte) { + if len(buf) == 0 { + return + } + _memset_neon(unsafe.Pointer(&buf[0]), uintptr(len(buf)), uintptr(c)) +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/memory/memory_neon_arm64.s b/vendor/github.com/apache/arrow/go/v14/arrow/memory/memory_neon_arm64.s new file mode 100644 index 000000000..18655cc7a --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/memory/memory_neon_arm64.s @@ -0,0 +1,43 @@ +//+build !noasm !appengine + +// ARROW-15320: +// (C2GOASM doesn't work correctly for Arm64) +// Partly GENERATED BY asm2plan9s. + +// func _memset_neon(buf unsafe.Pointer, len, c uintptr) +TEXT ·_memset_neon(SB), $0-24 + + MOVD buf+0(FP), R0 + MOVD len+8(FP), R1 + MOVD c+16(FP), R2 + + WORD $0xa9bf7bfd // stp x29, x30, [sp, #-16]! + WORD $0x8b010008 // add x8, x0, x1 + WORD $0xeb00011f // cmp x8, x0 + WORD $0x910003fd // mov x29, sp + BLS LBB0_7 + + WORD $0xf100803f // cmp x1, #32 + BHS LBB0_3 + WORD $0xaa0003e9 // mov x9, x0 + JMP LBB0_6 +LBB0_3: + WORD $0x927be82a // and x10, x1, #0xffffffffffffffe0 + WORD $0x4e010c40 // dup v0.16b, w2 + WORD $0x8b0a0009 // add x9, x0, x10 + WORD $0x9100400b // add x11, x0, #16 + WORD $0xaa0a03ec // mov x12, x10 +LBB0_4: + WORD $0xad3f8160 // stp q0, q0, [x11, #-16] + WORD $0xf100818c // subs x12, x12, #32 + WORD $0x9100816b // add x11, x11, #32 + BNE LBB0_4 + WORD $0xeb01015f // cmp x10, x1 + BEQ LBB0_7 +LBB0_6: + WORD $0x38001522 // strb w2, [x9], #1 + WORD $0xeb09011f // cmp x8, x9 + BNE LBB0_6 +LBB0_7: + WORD $0xa8c17bfd // ldp x29, x30, [sp], #16 + RET diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/memory/memory_noasm.go b/vendor/github.com/apache/arrow/go/v14/arrow/memory/memory_noasm.go new file mode 100644 index 000000000..bf8846fa2 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/memory/memory_noasm.go @@ -0,0 +1,23 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build noasm + +package memory + +func init() { + memset = memory_memset_go +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/memory/memory_sse4_amd64.go b/vendor/github.com/apache/arrow/go/v14/arrow/memory/memory_sse4_amd64.go new file mode 100644 index 000000000..716c0d270 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/memory/memory_sse4_amd64.go @@ -0,0 +1,31 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build !noasm + +package memory + +import "unsafe" + +//go:noescape +func _memset_sse4(buf unsafe.Pointer, len, c uintptr) + +func memory_memset_sse4(buf []byte, c byte) { + if len(buf) == 0 { + return + } + _memset_sse4(unsafe.Pointer(&buf[0]), uintptr(len(buf)), uintptr(c)) +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/memory/memory_sse4_amd64.s b/vendor/github.com/apache/arrow/go/v14/arrow/memory/memory_sse4_amd64.s new file mode 100644 index 000000000..b1906f99b --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/memory/memory_sse4_amd64.s @@ -0,0 +1,84 @@ +//+build !noasm !appengine +// AUTO-GENERATED BY C2GOASM -- DO NOT EDIT + +TEXT ·_memset_sse4(SB), $0-24 + + MOVQ buf+0(FP), DI + MOVQ len+8(FP), SI + MOVQ c+16(FP), DX + + LONG $0x371c8d4c // lea r11, [rdi + rsi] + WORD $0x3949; BYTE $0xfb // cmp r11, rdi + JBE LBB0_13 + LONG $0x20fe8348 // cmp rsi, 32 + JB LBB0_12 + WORD $0x8949; BYTE $0xf0 // mov r8, rsi + LONG $0xe0e08349 // and r8, -32 + WORD $0x8949; BYTE $0xf2 // mov r10, rsi + LONG $0xe0e28349 // and r10, -32 + JE LBB0_12 + WORD $0xb60f; BYTE $0xc2 // movzx eax, dl + LONG $0xc06e0f66 // movd xmm0, eax + LONG $0xc9ef0f66 // pxor xmm1, xmm1 + LONG $0x00380f66; BYTE $0xc1 // pshufb xmm0, xmm1 + LONG $0xe04a8d4d // lea r9, [r10 - 32] + WORD $0x8944; BYTE $0xc9 // mov ecx, r9d + WORD $0xe9c1; BYTE $0x05 // shr ecx, 5 + WORD $0xc1ff // inc ecx + LONG $0x07e18348 // and rcx, 7 + JE LBB0_4 + WORD $0xf748; BYTE $0xd9 // neg rcx + WORD $0xc031 // xor eax, eax + +LBB0_6: + LONG $0x047f0ff3; BYTE $0x07 // movdqu oword [rdi + rax], xmm0 + LONG $0x447f0ff3; WORD $0x1007 // movdqu oword [rdi + rax + 16], xmm0 + LONG $0x20c08348 // add rax, 32 + WORD $0xff48; BYTE $0xc1 // inc rcx + JNE LBB0_6 + JMP LBB0_7 + +LBB0_4: + WORD $0xc031 // xor eax, eax + +LBB0_7: + LONG $0xe0f98149; WORD $0x0000; BYTE $0x00 // cmp r9, 224 + JB LBB0_10 + WORD $0x894c; BYTE $0xd1 // mov rcx, r10 + WORD $0x2948; BYTE $0xc1 // sub rcx, rax + QUAD $0x000000f007848d48 // lea rax, [rdi + rax + 240] + +LBB0_9: + QUAD $0xffffff10807f0ff3 // movdqu oword [rax - 240], xmm0 + QUAD $0xffffff20807f0ff3 // movdqu oword [rax - 224], xmm0 + QUAD $0xffffff30807f0ff3 // movdqu oword [rax - 208], xmm0 + QUAD $0xffffff40807f0ff3 // movdqu oword [rax - 192], xmm0 + QUAD $0xffffff50807f0ff3 // movdqu oword [rax - 176], xmm0 + QUAD $0xffffff60807f0ff3 // movdqu oword [rax - 160], xmm0 + QUAD $0xffffff70807f0ff3 // movdqu oword [rax - 144], xmm0 + LONG $0x407f0ff3; BYTE $0x80 // movdqu oword [rax - 128], xmm0 + LONG $0x407f0ff3; BYTE $0x90 // movdqu oword [rax - 112], xmm0 + LONG $0x407f0ff3; BYTE $0xa0 // movdqu oword [rax - 96], xmm0 + LONG $0x407f0ff3; BYTE $0xb0 // movdqu oword [rax - 80], xmm0 + LONG $0x407f0ff3; BYTE $0xc0 // movdqu oword [rax - 64], xmm0 + LONG $0x407f0ff3; BYTE $0xd0 // movdqu oword [rax - 48], xmm0 + LONG $0x407f0ff3; BYTE $0xe0 // movdqu oword [rax - 32], xmm0 + LONG $0x407f0ff3; BYTE $0xf0 // movdqu oword [rax - 16], xmm0 + LONG $0x007f0ff3 // movdqu oword [rax], xmm0 + LONG $0x01000548; WORD $0x0000 // add rax, 256 + LONG $0x00c18148; WORD $0xffff; BYTE $0xff // add rcx, -256 + JNE LBB0_9 + +LBB0_10: + WORD $0x3949; BYTE $0xf2 // cmp r10, rsi + JE LBB0_13 + WORD $0x014c; BYTE $0xc7 // add rdi, r8 + +LBB0_12: + WORD $0x1788 // mov byte [rdi], dl + WORD $0xff48; BYTE $0xc7 // inc rdi + WORD $0x3949; BYTE $0xfb // cmp r11, rdi + JNE LBB0_12 + +LBB0_13: + RET diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/memory/util.go b/vendor/github.com/apache/arrow/go/v14/arrow/memory/util.go new file mode 100644 index 000000000..3b0d3a5cb --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/memory/util.go @@ -0,0 +1,37 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package memory + +import "unsafe" + +func roundToPowerOf2(v, round int) int { + forceCarry := round - 1 + truncateMask := ^forceCarry + return (v + forceCarry) & truncateMask +} + +func roundUpToMultipleOf64(v int) int { + return roundToPowerOf2(v, 64) +} + +func isMultipleOfPowerOf2(v int, d int) bool { + return (v & (d - 1)) == 0 +} + +func addressOf(b []byte) uintptr { + return uintptr(unsafe.Pointer(&b[0])) +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/numeric.schema.json b/vendor/github.com/apache/arrow/go/v14/arrow/numeric.schema.json new file mode 100644 index 000000000..7fa2800a5 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/numeric.schema.json @@ -0,0 +1,15 @@ +{ + "title": "templates", + "type": "array", + "items": { + "title": "template", + "type": "object", + "properties": { + "Name": { + "type": "string", + "description": "The name of the template type" + } + }, + "required": ["Name"] + } +} \ No newline at end of file diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/numeric.tmpldata b/vendor/github.com/apache/arrow/go/v14/arrow/numeric.tmpldata new file mode 100644 index 000000000..3c2d63b7c --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/numeric.tmpldata @@ -0,0 +1,135 @@ +[ + { + "Name": "Int64", + "name": "int64", + "Type": "int64", + "Default": "0", + "Size": "8", + "Opt": { + "BufferBuilder": true + } + }, + { + "Name": "Uint64", + "name": "uint64", + "Type": "uint64", + "Default": "0", + "Size": "8" + }, + { + "Name": "Float64", + "name": "float64", + "Type": "float64", + "Default": "0", + "Size": "8" + }, + { + "Name": "Int32", + "name": "int32", + "Type": "int32", + "Default": "0", + "Size": "4", + "Opt": { + "BufferBuilder": true + } + }, + { + "Name": "Uint32", + "name": "uint32", + "Type": "uint32", + "Default": "0", + "Size": "4" + }, + { + "Name": "Float32", + "name": "float32", + "Type": "float32", + "Default": "0", + "Size": "4" + }, + { + "Name": "Int16", + "name": "int16", + "Type": "int16", + "Default": "0", + "Size": "2" + }, + { + "Name": "Uint16", + "name": "uint16", + "Type": "uint16", + "Default": "0", + "Size": "2" + }, + { + "Name": "Int8", + "name": "int8", + "Type": "int8", + "Default": "0", + "Size": "1", + "Opt": { + "BufferBuilder": true + } + }, + { + "Name": "Uint8", + "name": "uint8", + "Type": "uint8", + "Default": "0", + "Size": "1" + }, + { + "Name": "Time32", + "name": "time32", + "Type": "Time32", + "QualifiedType": "arrow.Time32", + "InternalType": "int32", + "Default": "0", + "Size": "4", + "Opt": { + "Parametric": true + } + }, + { + "Name": "Time64", + "name": "time64", + "Type": "Time64", + "QualifiedType": "arrow.Time64", + "InternalType": "int64", + "Default": "0", + "Size": "8", + "Opt": { + "Parametric": true + } + }, + { + "Name": "Date32", + "name": "date32", + "Type": "Date32", + "QualifiedType": "arrow.Date32", + "InternalType": "int32", + "Default": "0", + "Size": "4" + }, + { + "Name": "Date64", + "name": "date64", + "Type": "Date64", + "QualifiedType": "arrow.Date64", + "InternalType": "int64", + "Default": "0", + "Size": "8" + }, + { + "Name": "Duration", + "name": "duration", + "Type": "Duration", + "QualifiedType": "arrow.Duration", + "InternalType": "int64", + "Default": "0", + "Size": "8", + "Opt": { + "Parametric": true + } + } +] diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/record.go b/vendor/github.com/apache/arrow/go/v14/arrow/record.go new file mode 100644 index 000000000..d98c7732e --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/record.go @@ -0,0 +1,49 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package arrow + +import "github.com/apache/arrow/go/v14/internal/json" + +// Record is a collection of equal-length arrays matching a particular Schema. +// Also known as a RecordBatch in the spec and in some implementations. +// +// It is also possible to construct a Table from a collection of Records that +// all have the same schema. +type Record interface { + json.Marshaler + + Release() + Retain() + + Schema() *Schema + + NumRows() int64 + NumCols() int64 + + Columns() []Array + Column(i int) Array + ColumnName(i int) string + SetColumn(i int, col Array) (Record, error) + + // NewSlice constructs a zero-copy slice of the record with the indicated + // indices i and j, corresponding to array[i:j]. + // The returned record must be Release()'d after use. + // + // NewSlice panics if the slice is outside the valid range of the record array. + // NewSlice panics if j < i. + NewSlice(i, j int64) Record +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/schema.go b/vendor/github.com/apache/arrow/go/v14/arrow/schema.go new file mode 100644 index 000000000..a7fa43413 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/schema.go @@ -0,0 +1,301 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package arrow + +import ( + "fmt" + "sort" + "strings" + + "github.com/apache/arrow/go/v14/arrow/endian" +) + +type Metadata struct { + keys []string + values []string +} + +func NewMetadata(keys, values []string) Metadata { + if len(keys) != len(values) { + panic("arrow: len mismatch") + } + + n := len(keys) + if n == 0 { + return Metadata{} + } + + md := Metadata{ + keys: make([]string, n), + values: make([]string, n), + } + copy(md.keys, keys) + copy(md.values, values) + return md +} + +func MetadataFrom(kv map[string]string) Metadata { + md := Metadata{ + keys: make([]string, 0, len(kv)), + values: make([]string, 0, len(kv)), + } + for k := range kv { + md.keys = append(md.keys, k) + } + sort.Strings(md.keys) + for _, k := range md.keys { + md.values = append(md.values, kv[k]) + } + return md +} + +func (md Metadata) Len() int { return len(md.keys) } +func (md Metadata) Keys() []string { return md.keys } +func (md Metadata) Values() []string { return md.values } +func (md Metadata) ToMap() map[string]string { + m := make(map[string]string, len(md.keys)) + for i := range md.keys { + m[md.keys[i]] = md.values[i] + } + return m +} + +func (md Metadata) String() string { + o := new(strings.Builder) + fmt.Fprintf(o, "[") + for i := range md.keys { + if i > 0 { + fmt.Fprintf(o, ", ") + } + fmt.Fprintf(o, "%q: %q", md.keys[i], md.values[i]) + } + fmt.Fprintf(o, "]") + return o.String() +} + +// FindKey returns the index of the key-value pair with the provided key name, +// or -1 if such a key does not exist. +func (md Metadata) FindKey(k string) int { + for i, v := range md.keys { + if v == k { + return i + } + } + return -1 +} + +// GetValue returns the value associated with the provided key name. +// If the key does not exist, the second return value is false. +func (md Metadata) GetValue(k string) (string, bool) { + i := md.FindKey(k) + if i < 0 { + return "", false + } + return md.values[i], true +} + +func (md Metadata) clone() Metadata { + if len(md.keys) == 0 { + return Metadata{} + } + + o := Metadata{ + keys: make([]string, len(md.keys)), + values: make([]string, len(md.values)), + } + copy(o.keys, md.keys) + copy(o.values, md.values) + + return o +} + +func (md Metadata) sortedIndices() []int { + idxes := make([]int, len(md.keys)) + for i := range idxes { + idxes[i] = i + } + + sort.Slice(idxes, func(i, j int) bool { + return md.keys[idxes[i]] < md.keys[idxes[j]] + }) + return idxes +} + +func (md Metadata) Equal(rhs Metadata) bool { + if md.Len() != rhs.Len() { + return false + } + + idxes := md.sortedIndices() + rhsIdxes := rhs.sortedIndices() + for i := range idxes { + j := idxes[i] + k := rhsIdxes[i] + if md.keys[j] != rhs.keys[k] || md.values[j] != rhs.values[k] { + return false + } + } + return true +} + +// Schema is a sequence of Field values, describing the columns of a table or +// a record batch. +type Schema struct { + fields []Field + index map[string][]int + meta Metadata + endianness endian.Endianness +} + +// NewSchema returns a new Schema value from the slice of fields and metadata. +// +// NewSchema panics if there is a field with an invalid DataType. +func NewSchema(fields []Field, metadata *Metadata) *Schema { + return NewSchemaWithEndian(fields, metadata, endian.NativeEndian) +} + +func NewSchemaWithEndian(fields []Field, metadata *Metadata, e endian.Endianness) *Schema { + sc := &Schema{ + fields: make([]Field, 0, len(fields)), + index: make(map[string][]int, len(fields)), + endianness: e, + } + if metadata != nil { + sc.meta = metadata.clone() + } + for i, field := range fields { + if field.Type == nil { + panic("arrow: field with nil DataType") + } + sc.fields = append(sc.fields, field) + sc.index[field.Name] = append(sc.index[field.Name], i) + } + return sc +} + +func (sc *Schema) WithEndianness(e endian.Endianness) *Schema { + return NewSchemaWithEndian(sc.fields, &sc.meta, e) +} + +func (sc *Schema) Endianness() endian.Endianness { return sc.endianness } +func (sc *Schema) IsNativeEndian() bool { return sc.endianness == endian.NativeEndian } +func (sc *Schema) Metadata() Metadata { return sc.meta } +func (sc *Schema) Fields() []Field { + fields := make([]Field, len(sc.fields)) + copy(fields, sc.fields) + return fields +} +func (sc *Schema) Field(i int) Field { return sc.fields[i] } +func (sc *Schema) NumFields() int { return len(sc.fields) } + +func (sc *Schema) FieldsByName(n string) ([]Field, bool) { + indices, ok := sc.index[n] + if !ok { + return nil, ok + } + fields := make([]Field, 0, len(indices)) + for _, v := range indices { + fields = append(fields, sc.fields[v]) + } + return fields, ok +} + +// FieldIndices returns the indices of the named field or nil. +func (sc *Schema) FieldIndices(n string) []int { + return sc.index[n] +} + +func (sc *Schema) HasField(n string) bool { return len(sc.FieldIndices(n)) > 0 } +func (sc *Schema) HasMetadata() bool { return len(sc.meta.keys) > 0 } + +// Equal returns whether two schema are equal. +// Equal does not compare the metadata. +func (sc *Schema) Equal(o *Schema) bool { + switch { + case sc == o: + return true + case sc == nil || o == nil: + return false + case len(sc.fields) != len(o.fields): + return false + case sc.endianness != o.endianness: + return false + } + + for i := range sc.fields { + if !sc.fields[i].Equal(o.fields[i]) { + return false + } + } + return true +} + +// AddField adds a field at the given index and return a new schema. +func (s *Schema) AddField(i int, field Field) (*Schema, error) { + if i < 0 || i > len(s.fields) { + return nil, fmt.Errorf("arrow: invalid field index %d", i) + } + + fields := make([]Field, len(s.fields)+1) + copy(fields[:i], s.fields[:i]) + fields[i] = field + copy(fields[i+1:], s.fields[i:]) + return NewSchema(fields, &s.meta), nil +} + +func (s *Schema) String() string { + o := new(strings.Builder) + fmt.Fprintf(o, "schema:\n fields: %d\n", len(s.Fields())) + for i, f := range s.Fields() { + if i > 0 { + o.WriteString("\n") + } + fmt.Fprintf(o, " - %v", f) + } + if s.endianness != endian.NativeEndian { + fmt.Fprintf(o, "\n endianness: %v", s.endianness) + } + if meta := s.Metadata(); meta.Len() > 0 { + fmt.Fprintf(o, "\n metadata: %v", meta) + } + return o.String() +} + +func (s *Schema) Fingerprint() string { + if s == nil { + return "" + } + + var b strings.Builder + b.WriteString("S{") + for _, f := range s.Fields() { + fieldFingerprint := f.Fingerprint() + if fieldFingerprint == "" { + return "" + } + + b.WriteString(fieldFingerprint) + b.WriteByte(';') + } + if s.endianness == endian.LittleEndian { + b.WriteByte('L') + } else { + b.WriteByte('B') + } + b.WriteByte('}') + return b.String() +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/table.go b/vendor/github.com/apache/arrow/go/v14/arrow/table.go new file mode 100644 index 000000000..5a68085f8 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/table.go @@ -0,0 +1,193 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package arrow + +import ( + "fmt" + "sync/atomic" + + "github.com/apache/arrow/go/v14/arrow/internal/debug" +) + +// Table represents a logical sequence of chunked arrays of equal length. It is +// similar to a Record except that the columns are ChunkedArrays instead, +// allowing for a Table to be built up by chunks progressively whereas the columns +// in a single Record are always each a single contiguous array. +type Table interface { + Schema() *Schema + NumRows() int64 + NumCols() int64 + Column(i int) *Column + + // AddColumn adds a new column to the table and a corresponding field (of the same type) + // to its schema, at the specified position. Returns the new table with updated columns and schema. + AddColumn(pos int, f Field, c Column) (Table, error) + + Retain() + Release() +} + +// Column is an immutable column data structure consisting of +// a field (type metadata) and a chunked data array. +// +// To get strongly typed data from a Column, you need to iterate the +// chunks and type assert each individual Array. For example: +// +// switch column.DataType().ID { +// case arrow.INT32: +// for _, c := range column.Data().Chunks() { +// arr := c.(*array.Int32) +// // do something with arr +// } +// case arrow.INT64: +// for _, c := range column.Data().Chunks() { +// arr := c.(*array.Int64) +// // do something with arr +// } +// case ... +// } +type Column struct { + field Field + data *Chunked +} + +// NewColumnFromArr is a convenience function to create a column from +// a field and a non-chunked array. +// +// This provides a simple mechanism for bypassing the middle step of +// constructing a Chunked array of one and then releasing it because +// of the ref counting. +func NewColumnFromArr(field Field, arr Array) Column { + if !TypeEqual(field.Type, arr.DataType()) { + panic(fmt.Errorf("%w: arrow/array: inconsistent data type %s vs %s", ErrInvalid, field.Type, arr.DataType())) + } + + arr.Retain() + return Column{ + field: field, + data: &Chunked{ + refCount: 1, + chunks: []Array{arr}, + length: arr.Len(), + nulls: arr.NullN(), + dtype: field.Type, + }, + } +} + +// NewColumn returns a column from a field and a chunked data array. +// +// NewColumn panics if the field's data type is inconsistent with the data type +// of the chunked data array. +func NewColumn(field Field, chunks *Chunked) *Column { + col := Column{ + field: field, + data: chunks, + } + col.data.Retain() + + if !TypeEqual(col.data.DataType(), col.field.Type) { + col.data.Release() + panic(fmt.Errorf("%w: arrow/array: inconsistent data type %s vs %s", ErrInvalid, col.data.DataType(), col.field.Type)) + } + + return &col +} + +// Retain increases the reference count by 1. +// Retain may be called simultaneously from multiple goroutines. +func (col *Column) Retain() { + col.data.Retain() +} + +// Release decreases the reference count by 1. +// When the reference count goes to zero, the memory is freed. +// Release may be called simultaneously from multiple goroutines. +func (col *Column) Release() { + col.data.Release() +} + +func (col *Column) Len() int { return col.data.Len() } +func (col *Column) NullN() int { return col.data.NullN() } +func (col *Column) Data() *Chunked { return col.data } +func (col *Column) Field() Field { return col.field } +func (col *Column) Name() string { return col.field.Name } +func (col *Column) DataType() DataType { return col.field.Type } + +// Chunked manages a collection of primitives arrays as one logical large array. +type Chunked struct { + refCount int64 // refCount must be first in the struct for 64 bit alignment and sync/atomic (https://github.com/golang/go/issues/37262) + + chunks []Array + + length int + nulls int + dtype DataType +} + +// NewChunked returns a new chunked array from the slice of arrays. +// +// NewChunked panics if the chunks do not have the same data type. +func NewChunked(dtype DataType, chunks []Array) *Chunked { + arr := &Chunked{ + chunks: make([]Array, 0, len(chunks)), + refCount: 1, + dtype: dtype, + } + for _, chunk := range chunks { + if chunk == nil { + continue + } + + if !TypeEqual(chunk.DataType(), dtype) { + panic(fmt.Errorf("%w: arrow/array: mismatch data type %s vs %s", ErrInvalid, chunk.DataType().String(), dtype.String())) + } + chunk.Retain() + arr.chunks = append(arr.chunks, chunk) + arr.length += chunk.Len() + arr.nulls += chunk.NullN() + } + return arr +} + +// Retain increases the reference count by 1. +// Retain may be called simultaneously from multiple goroutines. +func (a *Chunked) Retain() { + atomic.AddInt64(&a.refCount, 1) +} + +// Release decreases the reference count by 1. +// When the reference count goes to zero, the memory is freed. +// Release may be called simultaneously from multiple goroutines. +func (a *Chunked) Release() { + debug.Assert(atomic.LoadInt64(&a.refCount) > 0, "too many releases") + + if atomic.AddInt64(&a.refCount, -1) == 0 { + for _, arr := range a.chunks { + arr.Release() + } + a.chunks = nil + a.length = 0 + a.nulls = 0 + } +} + +func (a *Chunked) Len() int { return a.length } +func (a *Chunked) NullN() int { return a.nulls } +func (a *Chunked) DataType() DataType { return a.dtype } +func (a *Chunked) Chunks() []Array { return a.chunks } +func (a *Chunked) Chunk(i int) Array { return a.chunks[i] } diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/tools.go b/vendor/github.com/apache/arrow/go/v14/arrow/tools.go new file mode 100644 index 000000000..37b6dde36 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/tools.go @@ -0,0 +1,25 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build tools +// +build tools + +package tools + +import ( + _ "golang.org/x/tools/cmd/goimports" + _ "golang.org/x/tools/cmd/stringer" +) diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/type_string.go b/vendor/github.com/apache/arrow/go/v14/arrow/type_string.go new file mode 100644 index 000000000..ee3ccb7ef --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/type_string.go @@ -0,0 +1,65 @@ +// Code generated by "stringer -type=Type"; DO NOT EDIT. + +package arrow + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[NULL-0] + _ = x[BOOL-1] + _ = x[UINT8-2] + _ = x[INT8-3] + _ = x[UINT16-4] + _ = x[INT16-5] + _ = x[UINT32-6] + _ = x[INT32-7] + _ = x[UINT64-8] + _ = x[INT64-9] + _ = x[FLOAT16-10] + _ = x[FLOAT32-11] + _ = x[FLOAT64-12] + _ = x[STRING-13] + _ = x[BINARY-14] + _ = x[FIXED_SIZE_BINARY-15] + _ = x[DATE32-16] + _ = x[DATE64-17] + _ = x[TIMESTAMP-18] + _ = x[TIME32-19] + _ = x[TIME64-20] + _ = x[INTERVAL_MONTHS-21] + _ = x[INTERVAL_DAY_TIME-22] + _ = x[DECIMAL128-23] + _ = x[DECIMAL256-24] + _ = x[LIST-25] + _ = x[STRUCT-26] + _ = x[SPARSE_UNION-27] + _ = x[DENSE_UNION-28] + _ = x[DICTIONARY-29] + _ = x[MAP-30] + _ = x[EXTENSION-31] + _ = x[FIXED_SIZE_LIST-32] + _ = x[DURATION-33] + _ = x[LARGE_STRING-34] + _ = x[LARGE_BINARY-35] + _ = x[LARGE_LIST-36] + _ = x[INTERVAL_MONTH_DAY_NANO-37] + _ = x[RUN_END_ENCODED-38] + _ = x[STRING_VIEW-39] + _ = x[BINARY_VIEW-40] + _ = x[LIST_VIEW-41] + _ = x[LARGE_LIST_VIEW-42] +} + +const _Type_name = "NULLBOOLUINT8INT8UINT16INT16UINT32INT32UINT64INT64FLOAT16FLOAT32FLOAT64STRINGBINARYFIXED_SIZE_BINARYDATE32DATE64TIMESTAMPTIME32TIME64INTERVAL_MONTHSINTERVAL_DAY_TIMEDECIMAL128DECIMAL256LISTSTRUCTSPARSE_UNIONDENSE_UNIONDICTIONARYMAPEXTENSIONFIXED_SIZE_LISTDURATIONLARGE_STRINGLARGE_BINARYLARGE_LISTINTERVAL_MONTH_DAY_NANORUN_END_ENCODEDSTRING_VIEWBINARY_VIEWLIST_VIEWLARGE_LIST_VIEW" + +var _Type_index = [...]uint16{0, 4, 8, 13, 17, 23, 28, 34, 39, 45, 50, 57, 64, 71, 77, 83, 100, 106, 112, 121, 127, 133, 148, 165, 175, 185, 189, 195, 207, 218, 228, 231, 240, 255, 263, 275, 287, 297, 320, 335, 346, 357, 366, 381} + +func (i Type) String() string { + if i < 0 || i >= Type(len(_Type_index)-1) { + return "Type(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _Type_name[_Type_index[i]:_Type_index[i+1]] +} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/type_traits_boolean.go b/vendor/github.com/apache/arrow/go/v14/arrow/type_traits_boolean.go new file mode 100644 index 000000000..6a46bdec7 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/type_traits_boolean.go @@ -0,0 +1,28 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package arrow + +import ( + "github.com/apache/arrow/go/v14/arrow/bitutil" +) + +type booleanTraits struct{} + +var BooleanTraits booleanTraits + +// BytesRequired returns the number of bytes required to store n elements in memory. +func (booleanTraits) BytesRequired(n int) int { return bitutil.CeilByte(n) / 8 } diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/type_traits_decimal128.go b/vendor/github.com/apache/arrow/go/v14/arrow/type_traits_decimal128.go new file mode 100644 index 000000000..d2d3aae37 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/type_traits_decimal128.go @@ -0,0 +1,63 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package arrow + +import ( + "reflect" + "unsafe" + + "github.com/apache/arrow/go/v14/arrow/decimal128" + "github.com/apache/arrow/go/v14/arrow/endian" +) + +// Decimal128 traits +var Decimal128Traits decimal128Traits + +const ( + // Decimal128SizeBytes specifies the number of bytes required to store a single decimal128 in memory + Decimal128SizeBytes = int(unsafe.Sizeof(decimal128.Num{})) +) + +type decimal128Traits struct{} + +// BytesRequired returns the number of bytes required to store n elements in memory. +func (decimal128Traits) BytesRequired(n int) int { return Decimal128SizeBytes * n } + +// PutValue +func (decimal128Traits) PutValue(b []byte, v decimal128.Num) { + endian.Native.PutUint64(b[:8], uint64(v.LowBits())) + endian.Native.PutUint64(b[8:], uint64(v.HighBits())) +} + +// CastFromBytes reinterprets the slice b to a slice of type uint16. +// +// NOTE: len(b) must be a multiple of Uint16SizeBytes. +func (decimal128Traits) CastFromBytes(b []byte) []decimal128.Num { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*decimal128.Num)(unsafe.Pointer(h.Data)), cap(b)/Decimal128SizeBytes)[:len(b)/Decimal128SizeBytes] +} + +// CastToBytes reinterprets the slice b to a slice of bytes. +func (decimal128Traits) CastToBytes(b []decimal128.Num) []byte { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*byte)(unsafe.Pointer(h.Data)), cap(b)*Decimal128SizeBytes)[:len(b)*Decimal128SizeBytes] +} + +// Copy copies src to dst. +func (decimal128Traits) Copy(dst, src []decimal128.Num) { copy(dst, src) } diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/type_traits_decimal256.go b/vendor/github.com/apache/arrow/go/v14/arrow/type_traits_decimal256.go new file mode 100644 index 000000000..256ed68ff --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/type_traits_decimal256.go @@ -0,0 +1,58 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package arrow + +import ( + "reflect" + "unsafe" + + "github.com/apache/arrow/go/v14/arrow/decimal256" + "github.com/apache/arrow/go/v14/arrow/endian" +) + +// Decimal256 traits +var Decimal256Traits decimal256Traits + +const ( + Decimal256SizeBytes = int(unsafe.Sizeof(decimal256.Num{})) +) + +type decimal256Traits struct{} + +func (decimal256Traits) BytesRequired(n int) int { return Decimal256SizeBytes * n } + +func (decimal256Traits) PutValue(b []byte, v decimal256.Num) { + for i, a := range v.Array() { + start := i * 8 + endian.Native.PutUint64(b[start:], a) + } +} + +// CastFromBytes reinterprets the slice b to a slice of decimal256 +func (decimal256Traits) CastFromBytes(b []byte) []decimal256.Num { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*decimal256.Num)(unsafe.Pointer(h.Data)), cap(b)/Decimal256SizeBytes)[:len(b)/Decimal256SizeBytes] +} + +func (decimal256Traits) CastToBytes(b []decimal256.Num) []byte { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*byte)(unsafe.Pointer(h.Data)), cap(b)*Decimal256SizeBytes)[:len(b)*Decimal256SizeBytes] +} + +func (decimal256Traits) Copy(dst, src []decimal256.Num) { copy(dst, src) } diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/type_traits_float16.go b/vendor/github.com/apache/arrow/go/v14/arrow/type_traits_float16.go new file mode 100644 index 000000000..c40363d37 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/type_traits_float16.go @@ -0,0 +1,62 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package arrow + +import ( + "reflect" + "unsafe" + + "github.com/apache/arrow/go/v14/arrow/endian" + "github.com/apache/arrow/go/v14/arrow/float16" +) + +// Float16 traits +var Float16Traits float16Traits + +const ( + // Float16SizeBytes specifies the number of bytes required to store a single float16 in memory + Float16SizeBytes = int(unsafe.Sizeof(uint16(0))) +) + +type float16Traits struct{} + +// BytesRequired returns the number of bytes required to store n elements in memory. +func (float16Traits) BytesRequired(n int) int { return Float16SizeBytes * n } + +// PutValue +func (float16Traits) PutValue(b []byte, v float16.Num) { + endian.Native.PutUint16(b, uint16(v.Uint16())) +} + +// CastFromBytes reinterprets the slice b to a slice of type uint16. +// +// NOTE: len(b) must be a multiple of Uint16SizeBytes. +func (float16Traits) CastFromBytes(b []byte) []float16.Num { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*float16.Num)(unsafe.Pointer(h.Data)), cap(b)/Float16SizeBytes)[:len(b)/Float16SizeBytes] +} + +// CastToBytes reinterprets the slice b to a slice of bytes. +func (float16Traits) CastToBytes(b []float16.Num) []byte { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*byte)(unsafe.Pointer(h.Data)), cap(b)*Float16SizeBytes)[:len(b)*Float16SizeBytes] +} + +// Copy copies src to dst. +func (float16Traits) Copy(dst, src []float16.Num) { copy(dst, src) } diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/type_traits_interval.go b/vendor/github.com/apache/arrow/go/v14/arrow/type_traits_interval.go new file mode 100644 index 000000000..35e605709 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/type_traits_interval.go @@ -0,0 +1,148 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package arrow + +import ( + "reflect" + "unsafe" + + "github.com/apache/arrow/go/v14/arrow/endian" + "github.com/apache/arrow/go/v14/arrow/internal/debug" +) + +var ( + MonthIntervalTraits monthTraits + DayTimeIntervalTraits daytimeTraits + MonthDayNanoIntervalTraits monthDayNanoTraits +) + +func init() { + debug.Assert(MonthIntervalSizeBytes == 4, "MonthIntervalSizeBytes should be 4") + debug.Assert(DayTimeIntervalSizeBytes == 8, "DayTimeIntervalSizeBytes should be 8") + debug.Assert(MonthDayNanoIntervalSizeBytes == 16, "MonthDayNanoIntervalSizeBytes should be 16") +} + +// MonthInterval traits + +const ( + // MonthIntervalSizeBytes specifies the number of bytes required to store a single MonthInterval in memory + MonthIntervalSizeBytes = int(unsafe.Sizeof(MonthInterval(0))) +) + +type monthTraits struct{} + +// BytesRequired returns the number of bytes required to store n elements in memory. +func (monthTraits) BytesRequired(n int) int { return MonthIntervalSizeBytes * n } + +// PutValue +func (monthTraits) PutValue(b []byte, v MonthInterval) { + endian.Native.PutUint32(b, uint32(v)) +} + +// CastFromBytes reinterprets the slice b to a slice of type MonthInterval. +// +// NOTE: len(b) must be a multiple of MonthIntervalSizeBytes. +func (monthTraits) CastFromBytes(b []byte) []MonthInterval { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*MonthInterval)(unsafe.Pointer(h.Data)), cap(b)/MonthIntervalSizeBytes)[:len(b)/MonthIntervalSizeBytes] +} + +// CastToBytes reinterprets the slice b to a slice of bytes. +func (monthTraits) CastToBytes(b []MonthInterval) []byte { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*byte)(unsafe.Pointer(h.Data)), cap(b)*MonthIntervalSizeBytes)[:len(b)*MonthIntervalSizeBytes] +} + +// Copy copies src to dst. +func (monthTraits) Copy(dst, src []MonthInterval) { copy(dst, src) } + +// DayTimeInterval traits + +const ( + // DayTimeIntervalSizeBytes specifies the number of bytes required to store a single DayTimeInterval in memory + DayTimeIntervalSizeBytes = int(unsafe.Sizeof(DayTimeInterval{})) +) + +type daytimeTraits struct{} + +// BytesRequired returns the number of bytes required to store n elements in memory. +func (daytimeTraits) BytesRequired(n int) int { return DayTimeIntervalSizeBytes * n } + +// PutValue +func (daytimeTraits) PutValue(b []byte, v DayTimeInterval) { + endian.Native.PutUint32(b[0:4], uint32(v.Days)) + endian.Native.PutUint32(b[4:8], uint32(v.Milliseconds)) +} + +// CastFromBytes reinterprets the slice b to a slice of type DayTimeInterval. +// +// NOTE: len(b) must be a multiple of DayTimeIntervalSizeBytes. +func (daytimeTraits) CastFromBytes(b []byte) []DayTimeInterval { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*DayTimeInterval)(unsafe.Pointer(h.Data)), cap(b)/DayTimeIntervalSizeBytes)[:len(b)/DayTimeIntervalSizeBytes] +} + +// CastToBytes reinterprets the slice b to a slice of bytes. +func (daytimeTraits) CastToBytes(b []DayTimeInterval) []byte { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*byte)(unsafe.Pointer(h.Data)), cap(b)*DayTimeIntervalSizeBytes)[:len(b)*DayTimeIntervalSizeBytes] +} + +// Copy copies src to dst. +func (daytimeTraits) Copy(dst, src []DayTimeInterval) { copy(dst, src) } + +// DayTimeInterval traits + +const ( + // MonthDayNanoIntervalSizeBytes specifies the number of bytes required to store a single DayTimeInterval in memory + MonthDayNanoIntervalSizeBytes = int(unsafe.Sizeof(MonthDayNanoInterval{})) +) + +type monthDayNanoTraits struct{} + +// BytesRequired returns the number of bytes required to store n elements in memory. +func (monthDayNanoTraits) BytesRequired(n int) int { return MonthDayNanoIntervalSizeBytes * n } + +// PutValue +func (monthDayNanoTraits) PutValue(b []byte, v MonthDayNanoInterval) { + endian.Native.PutUint32(b[0:4], uint32(v.Months)) + endian.Native.PutUint32(b[4:8], uint32(v.Days)) + endian.Native.PutUint64(b[8:], uint64(v.Nanoseconds)) +} + +// CastFromBytes reinterprets the slice b to a slice of type MonthDayNanoInterval. +// +// NOTE: len(b) must be a multiple of MonthDayNanoIntervalSizeBytes. +func (monthDayNanoTraits) CastFromBytes(b []byte) []MonthDayNanoInterval { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*MonthDayNanoInterval)(unsafe.Pointer(h.Data)), cap(b)/MonthDayNanoIntervalSizeBytes)[:len(b)/MonthDayNanoIntervalSizeBytes] +} + +// CastToBytes reinterprets the slice b to a slice of bytes. +func (monthDayNanoTraits) CastToBytes(b []MonthDayNanoInterval) []byte { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*byte)(unsafe.Pointer(h.Data)), cap(b)*MonthDayNanoIntervalSizeBytes)[:len(b)*MonthDayNanoIntervalSizeBytes] +} + +// Copy copies src to dst. +func (monthDayNanoTraits) Copy(dst, src []MonthDayNanoInterval) { copy(dst, src) } diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/type_traits_numeric.gen.go b/vendor/github.com/apache/arrow/go/v14/arrow/type_traits_numeric.gen.go new file mode 100644 index 000000000..6edd75291 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/type_traits_numeric.gen.go @@ -0,0 +1,585 @@ +// Code generated by type_traits_numeric.gen.go.tmpl. DO NOT EDIT. + +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package arrow + +import ( + "math" + "reflect" + "unsafe" + + "github.com/apache/arrow/go/v14/arrow/endian" +) + +var ( + Int64Traits int64Traits + Uint64Traits uint64Traits + Float64Traits float64Traits + Int32Traits int32Traits + Uint32Traits uint32Traits + Float32Traits float32Traits + Int16Traits int16Traits + Uint16Traits uint16Traits + Int8Traits int8Traits + Uint8Traits uint8Traits + Time32Traits time32Traits + Time64Traits time64Traits + Date32Traits date32Traits + Date64Traits date64Traits + DurationTraits durationTraits +) + +// Int64 traits + +const ( + // Int64SizeBytes specifies the number of bytes required to store a single int64 in memory + Int64SizeBytes = int(unsafe.Sizeof(int64(0))) +) + +type int64Traits struct{} + +// BytesRequired returns the number of bytes required to store n elements in memory. +func (int64Traits) BytesRequired(n int) int { return Int64SizeBytes * n } + +// PutValue +func (int64Traits) PutValue(b []byte, v int64) { + endian.Native.PutUint64(b, uint64(v)) +} + +// CastFromBytes reinterprets the slice b to a slice of type int64. +// +// NOTE: len(b) must be a multiple of Int64SizeBytes. +func (int64Traits) CastFromBytes(b []byte) []int64 { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*int64)(unsafe.Pointer(h.Data)), cap(b)/Int64SizeBytes)[:len(b)/Int64SizeBytes] +} + +// CastToBytes reinterprets the slice b to a slice of bytes. +func (int64Traits) CastToBytes(b []int64) []byte { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*byte)(unsafe.Pointer(h.Data)), cap(b)*Int64SizeBytes)[:len(b)*Int64SizeBytes] +} + +// Copy copies src to dst. +func (int64Traits) Copy(dst, src []int64) { copy(dst, src) } + +// Uint64 traits + +const ( + // Uint64SizeBytes specifies the number of bytes required to store a single uint64 in memory + Uint64SizeBytes = int(unsafe.Sizeof(uint64(0))) +) + +type uint64Traits struct{} + +// BytesRequired returns the number of bytes required to store n elements in memory. +func (uint64Traits) BytesRequired(n int) int { return Uint64SizeBytes * n } + +// PutValue +func (uint64Traits) PutValue(b []byte, v uint64) { + endian.Native.PutUint64(b, uint64(v)) +} + +// CastFromBytes reinterprets the slice b to a slice of type uint64. +// +// NOTE: len(b) must be a multiple of Uint64SizeBytes. +func (uint64Traits) CastFromBytes(b []byte) []uint64 { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*uint64)(unsafe.Pointer(h.Data)), cap(b)/Uint64SizeBytes)[:len(b)/Uint64SizeBytes] +} + +// CastToBytes reinterprets the slice b to a slice of bytes. +func (uint64Traits) CastToBytes(b []uint64) []byte { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*byte)(unsafe.Pointer(h.Data)), cap(b)*Uint64SizeBytes)[:len(b)*Uint64SizeBytes] +} + +// Copy copies src to dst. +func (uint64Traits) Copy(dst, src []uint64) { copy(dst, src) } + +// Float64 traits + +const ( + // Float64SizeBytes specifies the number of bytes required to store a single float64 in memory + Float64SizeBytes = int(unsafe.Sizeof(float64(0))) +) + +type float64Traits struct{} + +// BytesRequired returns the number of bytes required to store n elements in memory. +func (float64Traits) BytesRequired(n int) int { return Float64SizeBytes * n } + +// PutValue +func (float64Traits) PutValue(b []byte, v float64) { + endian.Native.PutUint64(b, math.Float64bits(v)) +} + +// CastFromBytes reinterprets the slice b to a slice of type float64. +// +// NOTE: len(b) must be a multiple of Float64SizeBytes. +func (float64Traits) CastFromBytes(b []byte) []float64 { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*float64)(unsafe.Pointer(h.Data)), cap(b)/Float64SizeBytes)[:len(b)/Float64SizeBytes] +} + +// CastToBytes reinterprets the slice b to a slice of bytes. +func (float64Traits) CastToBytes(b []float64) []byte { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*byte)(unsafe.Pointer(h.Data)), cap(b)*Float64SizeBytes)[:len(b)*Float64SizeBytes] +} + +// Copy copies src to dst. +func (float64Traits) Copy(dst, src []float64) { copy(dst, src) } + +// Int32 traits + +const ( + // Int32SizeBytes specifies the number of bytes required to store a single int32 in memory + Int32SizeBytes = int(unsafe.Sizeof(int32(0))) +) + +type int32Traits struct{} + +// BytesRequired returns the number of bytes required to store n elements in memory. +func (int32Traits) BytesRequired(n int) int { return Int32SizeBytes * n } + +// PutValue +func (int32Traits) PutValue(b []byte, v int32) { + endian.Native.PutUint32(b, uint32(v)) +} + +// CastFromBytes reinterprets the slice b to a slice of type int32. +// +// NOTE: len(b) must be a multiple of Int32SizeBytes. +func (int32Traits) CastFromBytes(b []byte) []int32 { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*int32)(unsafe.Pointer(h.Data)), cap(b)/Int32SizeBytes)[:len(b)/Int32SizeBytes] +} + +// CastToBytes reinterprets the slice b to a slice of bytes. +func (int32Traits) CastToBytes(b []int32) []byte { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*byte)(unsafe.Pointer(h.Data)), cap(b)*Int32SizeBytes)[:len(b)*Int32SizeBytes] +} + +// Copy copies src to dst. +func (int32Traits) Copy(dst, src []int32) { copy(dst, src) } + +// Uint32 traits + +const ( + // Uint32SizeBytes specifies the number of bytes required to store a single uint32 in memory + Uint32SizeBytes = int(unsafe.Sizeof(uint32(0))) +) + +type uint32Traits struct{} + +// BytesRequired returns the number of bytes required to store n elements in memory. +func (uint32Traits) BytesRequired(n int) int { return Uint32SizeBytes * n } + +// PutValue +func (uint32Traits) PutValue(b []byte, v uint32) { + endian.Native.PutUint32(b, uint32(v)) +} + +// CastFromBytes reinterprets the slice b to a slice of type uint32. +// +// NOTE: len(b) must be a multiple of Uint32SizeBytes. +func (uint32Traits) CastFromBytes(b []byte) []uint32 { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*uint32)(unsafe.Pointer(h.Data)), cap(b)/Uint32SizeBytes)[:len(b)/Uint32SizeBytes] +} + +// CastToBytes reinterprets the slice b to a slice of bytes. +func (uint32Traits) CastToBytes(b []uint32) []byte { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*byte)(unsafe.Pointer(h.Data)), cap(b)*Uint32SizeBytes)[:len(b)*Uint32SizeBytes] +} + +// Copy copies src to dst. +func (uint32Traits) Copy(dst, src []uint32) { copy(dst, src) } + +// Float32 traits + +const ( + // Float32SizeBytes specifies the number of bytes required to store a single float32 in memory + Float32SizeBytes = int(unsafe.Sizeof(float32(0))) +) + +type float32Traits struct{} + +// BytesRequired returns the number of bytes required to store n elements in memory. +func (float32Traits) BytesRequired(n int) int { return Float32SizeBytes * n } + +// PutValue +func (float32Traits) PutValue(b []byte, v float32) { + endian.Native.PutUint32(b, math.Float32bits(v)) +} + +// CastFromBytes reinterprets the slice b to a slice of type float32. +// +// NOTE: len(b) must be a multiple of Float32SizeBytes. +func (float32Traits) CastFromBytes(b []byte) []float32 { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*float32)(unsafe.Pointer(h.Data)), cap(b)/Float32SizeBytes)[:len(b)/Float32SizeBytes] +} + +// CastToBytes reinterprets the slice b to a slice of bytes. +func (float32Traits) CastToBytes(b []float32) []byte { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*byte)(unsafe.Pointer(h.Data)), cap(b)*Float32SizeBytes)[:len(b)*Float32SizeBytes] +} + +// Copy copies src to dst. +func (float32Traits) Copy(dst, src []float32) { copy(dst, src) } + +// Int16 traits + +const ( + // Int16SizeBytes specifies the number of bytes required to store a single int16 in memory + Int16SizeBytes = int(unsafe.Sizeof(int16(0))) +) + +type int16Traits struct{} + +// BytesRequired returns the number of bytes required to store n elements in memory. +func (int16Traits) BytesRequired(n int) int { return Int16SizeBytes * n } + +// PutValue +func (int16Traits) PutValue(b []byte, v int16) { + endian.Native.PutUint16(b, uint16(v)) +} + +// CastFromBytes reinterprets the slice b to a slice of type int16. +// +// NOTE: len(b) must be a multiple of Int16SizeBytes. +func (int16Traits) CastFromBytes(b []byte) []int16 { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*int16)(unsafe.Pointer(h.Data)), cap(b)/Int16SizeBytes)[:len(b)/Int16SizeBytes] +} + +// CastToBytes reinterprets the slice b to a slice of bytes. +func (int16Traits) CastToBytes(b []int16) []byte { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*byte)(unsafe.Pointer(h.Data)), cap(b)*Int16SizeBytes)[:len(b)*Int16SizeBytes] +} + +// Copy copies src to dst. +func (int16Traits) Copy(dst, src []int16) { copy(dst, src) } + +// Uint16 traits + +const ( + // Uint16SizeBytes specifies the number of bytes required to store a single uint16 in memory + Uint16SizeBytes = int(unsafe.Sizeof(uint16(0))) +) + +type uint16Traits struct{} + +// BytesRequired returns the number of bytes required to store n elements in memory. +func (uint16Traits) BytesRequired(n int) int { return Uint16SizeBytes * n } + +// PutValue +func (uint16Traits) PutValue(b []byte, v uint16) { + endian.Native.PutUint16(b, uint16(v)) +} + +// CastFromBytes reinterprets the slice b to a slice of type uint16. +// +// NOTE: len(b) must be a multiple of Uint16SizeBytes. +func (uint16Traits) CastFromBytes(b []byte) []uint16 { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*uint16)(unsafe.Pointer(h.Data)), cap(b)/Uint16SizeBytes)[:len(b)/Uint16SizeBytes] +} + +// CastToBytes reinterprets the slice b to a slice of bytes. +func (uint16Traits) CastToBytes(b []uint16) []byte { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*byte)(unsafe.Pointer(h.Data)), cap(b)*Uint16SizeBytes)[:len(b)*Uint16SizeBytes] +} + +// Copy copies src to dst. +func (uint16Traits) Copy(dst, src []uint16) { copy(dst, src) } + +// Int8 traits + +const ( + // Int8SizeBytes specifies the number of bytes required to store a single int8 in memory + Int8SizeBytes = int(unsafe.Sizeof(int8(0))) +) + +type int8Traits struct{} + +// BytesRequired returns the number of bytes required to store n elements in memory. +func (int8Traits) BytesRequired(n int) int { return Int8SizeBytes * n } + +// PutValue +func (int8Traits) PutValue(b []byte, v int8) { + b[0] = byte(v) +} + +// CastFromBytes reinterprets the slice b to a slice of type int8. +// +// NOTE: len(b) must be a multiple of Int8SizeBytes. +func (int8Traits) CastFromBytes(b []byte) []int8 { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*int8)(unsafe.Pointer(h.Data)), cap(b)/Int8SizeBytes)[:len(b)/Int8SizeBytes] +} + +// CastToBytes reinterprets the slice b to a slice of bytes. +func (int8Traits) CastToBytes(b []int8) []byte { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*byte)(unsafe.Pointer(h.Data)), cap(b)*Int8SizeBytes)[:len(b)*Int8SizeBytes] +} + +// Copy copies src to dst. +func (int8Traits) Copy(dst, src []int8) { copy(dst, src) } + +// Uint8 traits + +const ( + // Uint8SizeBytes specifies the number of bytes required to store a single uint8 in memory + Uint8SizeBytes = int(unsafe.Sizeof(uint8(0))) +) + +type uint8Traits struct{} + +// BytesRequired returns the number of bytes required to store n elements in memory. +func (uint8Traits) BytesRequired(n int) int { return Uint8SizeBytes * n } + +// PutValue +func (uint8Traits) PutValue(b []byte, v uint8) { + b[0] = byte(v) +} + +// CastFromBytes reinterprets the slice b to a slice of type uint8. +// +// NOTE: len(b) must be a multiple of Uint8SizeBytes. +func (uint8Traits) CastFromBytes(b []byte) []uint8 { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*uint8)(unsafe.Pointer(h.Data)), cap(b)/Uint8SizeBytes)[:len(b)/Uint8SizeBytes] +} + +// CastToBytes reinterprets the slice b to a slice of bytes. +func (uint8Traits) CastToBytes(b []uint8) []byte { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*byte)(unsafe.Pointer(h.Data)), cap(b)*Uint8SizeBytes)[:len(b)*Uint8SizeBytes] +} + +// Copy copies src to dst. +func (uint8Traits) Copy(dst, src []uint8) { copy(dst, src) } + +// Time32 traits + +const ( + // Time32SizeBytes specifies the number of bytes required to store a single Time32 in memory + Time32SizeBytes = int(unsafe.Sizeof(Time32(0))) +) + +type time32Traits struct{} + +// BytesRequired returns the number of bytes required to store n elements in memory. +func (time32Traits) BytesRequired(n int) int { return Time32SizeBytes * n } + +// PutValue +func (time32Traits) PutValue(b []byte, v Time32) { + endian.Native.PutUint32(b, uint32(v)) +} + +// CastFromBytes reinterprets the slice b to a slice of type Time32. +// +// NOTE: len(b) must be a multiple of Time32SizeBytes. +func (time32Traits) CastFromBytes(b []byte) []Time32 { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*Time32)(unsafe.Pointer(h.Data)), cap(b)/Time32SizeBytes)[:len(b)/Time32SizeBytes] +} + +// CastToBytes reinterprets the slice b to a slice of bytes. +func (time32Traits) CastToBytes(b []Time32) []byte { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*byte)(unsafe.Pointer(h.Data)), cap(b)*Time32SizeBytes)[:len(b)*Time32SizeBytes] +} + +// Copy copies src to dst. +func (time32Traits) Copy(dst, src []Time32) { copy(dst, src) } + +// Time64 traits + +const ( + // Time64SizeBytes specifies the number of bytes required to store a single Time64 in memory + Time64SizeBytes = int(unsafe.Sizeof(Time64(0))) +) + +type time64Traits struct{} + +// BytesRequired returns the number of bytes required to store n elements in memory. +func (time64Traits) BytesRequired(n int) int { return Time64SizeBytes * n } + +// PutValue +func (time64Traits) PutValue(b []byte, v Time64) { + endian.Native.PutUint64(b, uint64(v)) +} + +// CastFromBytes reinterprets the slice b to a slice of type Time64. +// +// NOTE: len(b) must be a multiple of Time64SizeBytes. +func (time64Traits) CastFromBytes(b []byte) []Time64 { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*Time64)(unsafe.Pointer(h.Data)), cap(b)/Time64SizeBytes)[:len(b)/Time64SizeBytes] +} + +// CastToBytes reinterprets the slice b to a slice of bytes. +func (time64Traits) CastToBytes(b []Time64) []byte { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*byte)(unsafe.Pointer(h.Data)), cap(b)*Time64SizeBytes)[:len(b)*Time64SizeBytes] +} + +// Copy copies src to dst. +func (time64Traits) Copy(dst, src []Time64) { copy(dst, src) } + +// Date32 traits + +const ( + // Date32SizeBytes specifies the number of bytes required to store a single Date32 in memory + Date32SizeBytes = int(unsafe.Sizeof(Date32(0))) +) + +type date32Traits struct{} + +// BytesRequired returns the number of bytes required to store n elements in memory. +func (date32Traits) BytesRequired(n int) int { return Date32SizeBytes * n } + +// PutValue +func (date32Traits) PutValue(b []byte, v Date32) { + endian.Native.PutUint32(b, uint32(v)) +} + +// CastFromBytes reinterprets the slice b to a slice of type Date32. +// +// NOTE: len(b) must be a multiple of Date32SizeBytes. +func (date32Traits) CastFromBytes(b []byte) []Date32 { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*Date32)(unsafe.Pointer(h.Data)), cap(b)/Date32SizeBytes)[:len(b)/Date32SizeBytes] +} + +// CastToBytes reinterprets the slice b to a slice of bytes. +func (date32Traits) CastToBytes(b []Date32) []byte { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*byte)(unsafe.Pointer(h.Data)), cap(b)*Date32SizeBytes)[:len(b)*Date32SizeBytes] +} + +// Copy copies src to dst. +func (date32Traits) Copy(dst, src []Date32) { copy(dst, src) } + +// Date64 traits + +const ( + // Date64SizeBytes specifies the number of bytes required to store a single Date64 in memory + Date64SizeBytes = int(unsafe.Sizeof(Date64(0))) +) + +type date64Traits struct{} + +// BytesRequired returns the number of bytes required to store n elements in memory. +func (date64Traits) BytesRequired(n int) int { return Date64SizeBytes * n } + +// PutValue +func (date64Traits) PutValue(b []byte, v Date64) { + endian.Native.PutUint64(b, uint64(v)) +} + +// CastFromBytes reinterprets the slice b to a slice of type Date64. +// +// NOTE: len(b) must be a multiple of Date64SizeBytes. +func (date64Traits) CastFromBytes(b []byte) []Date64 { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*Date64)(unsafe.Pointer(h.Data)), cap(b)/Date64SizeBytes)[:len(b)/Date64SizeBytes] +} + +// CastToBytes reinterprets the slice b to a slice of bytes. +func (date64Traits) CastToBytes(b []Date64) []byte { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*byte)(unsafe.Pointer(h.Data)), cap(b)*Date64SizeBytes)[:len(b)*Date64SizeBytes] +} + +// Copy copies src to dst. +func (date64Traits) Copy(dst, src []Date64) { copy(dst, src) } + +// Duration traits + +const ( + // DurationSizeBytes specifies the number of bytes required to store a single Duration in memory + DurationSizeBytes = int(unsafe.Sizeof(Duration(0))) +) + +type durationTraits struct{} + +// BytesRequired returns the number of bytes required to store n elements in memory. +func (durationTraits) BytesRequired(n int) int { return DurationSizeBytes * n } + +// PutValue +func (durationTraits) PutValue(b []byte, v Duration) { + endian.Native.PutUint64(b, uint64(v)) +} + +// CastFromBytes reinterprets the slice b to a slice of type Duration. +// +// NOTE: len(b) must be a multiple of DurationSizeBytes. +func (durationTraits) CastFromBytes(b []byte) []Duration { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*Duration)(unsafe.Pointer(h.Data)), cap(b)/DurationSizeBytes)[:len(b)/DurationSizeBytes] +} + +// CastToBytes reinterprets the slice b to a slice of bytes. +func (durationTraits) CastToBytes(b []Duration) []byte { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*byte)(unsafe.Pointer(h.Data)), cap(b)*DurationSizeBytes)[:len(b)*DurationSizeBytes] +} + +// Copy copies src to dst. +func (durationTraits) Copy(dst, src []Duration) { copy(dst, src) } diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/type_traits_numeric.gen.go.tmpl b/vendor/github.com/apache/arrow/go/v14/arrow/type_traits_numeric.gen.go.tmpl new file mode 100644 index 000000000..ffae975c1 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/type_traits_numeric.gen.go.tmpl @@ -0,0 +1,83 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package arrow + +import ( + "math" + "reflect" + "unsafe" + + "github.com/apache/arrow/go/v14/arrow/endian" +) + +var ( +{{range .In}} + {{.Name}}Traits {{.name}}Traits +{{- end}} +) + +{{range .In}} +// {{.Name}} traits + +const ( + // {{.Name}}SizeBytes specifies the number of bytes required to store a single {{.Type}} in memory + {{.Name}}SizeBytes = int(unsafe.Sizeof({{.Type}}({{.Default}}))) +) + +type {{.name}}Traits struct{} + +// BytesRequired returns the number of bytes required to store n elements in memory. +func ({{.name}}Traits) BytesRequired(n int) int { return {{.Name}}SizeBytes * n } + +// PutValue +func ({{.name}}Traits) PutValue(b []byte, v {{.Type}}) { +{{- if eq .Type "float32" -}} + endian.Native.PutUint32(b, math.Float32bits(v)) +{{- else if eq .Type "float64" -}} + endian.Native.PutUint64(b, math.Float64bits(v)) +{{- else if eq .Size "1" -}} + b[0] = byte(v) +{{- else if eq .Size "2" -}} + endian.Native.PutUint16(b, uint16(v)) +{{- else if eq .Size "4" -}} + endian.Native.PutUint32(b, uint32(v)) +{{- else if eq .Size "8" -}} + endian.Native.PutUint64(b, uint64(v)) +{{- else -}} + panic("invalid type {{.Type}}") +{{end}} +} + +// CastFromBytes reinterprets the slice b to a slice of type {{.Type}}. +// +// NOTE: len(b) must be a multiple of {{.Name}}SizeBytes. +func ({{.name}}Traits) CastFromBytes(b []byte) []{{.Type}} { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*{{.Type}})(unsafe.Pointer(h.Data)), cap(b)/{{.Name}}SizeBytes)[:len(b)/{{.Name}}SizeBytes] +} + +// CastToBytes reinterprets the slice b to a slice of bytes. +func ({{.name}}Traits) CastToBytes(b []{{.Type}}) []byte { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*byte)(unsafe.Pointer(h.Data)), cap(b)*{{.Name}}SizeBytes)[:len(b)*{{.Name}}SizeBytes] +} + +// Copy copies src to dst. +func ({{.name}}Traits) Copy(dst, src []{{.Type}}) { copy(dst, src) } +{{end}} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/type_traits_numeric.gen_test.go.tmpl b/vendor/github.com/apache/arrow/go/v14/arrow/type_traits_numeric.gen_test.go.tmpl new file mode 100644 index 000000000..96685f313 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/type_traits_numeric.gen_test.go.tmpl @@ -0,0 +1,61 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package arrow_test + +import ( + "reflect" + "testing" + + "github.com/apache/arrow/go/v14/arrow" +) + +{{- range .In}} + +func Test{{.Name}}Traits(t *testing.T) { + const N = 10 + b1 := arrow.{{.Name}}Traits.CastToBytes([]{{or .QualifiedType .Type}}{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + }) + + b2 := make([]byte, arrow.{{.Name}}Traits.BytesRequired(N)) + for i := 0; i < N; i++ { + beg := i * arrow.{{.Name}}SizeBytes + end := (i + 1) * arrow.{{.Name}}SizeBytes + arrow.{{.Name}}Traits.PutValue(b2[beg:end], {{or .QualifiedType .Type}}(i)) + } + + if !reflect.DeepEqual(b1, b2) { + v1 := arrow.{{.Name}}Traits.CastFromBytes(b1) + v2 := arrow.{{.Name}}Traits.CastFromBytes(b2) + t.Fatalf("invalid values:\nb1=%v\nb2=%v\nv1=%v\nv2=%v\n", b1, b2, v1, v2) + } + + v1 := arrow.{{.Name}}Traits.CastFromBytes(b1) + for i, v := range v1 { + if got, want := v, {{or .QualifiedType .Type}}(i); got != want { + t.Fatalf("invalid value[%d]. got=%v, want=%v", i, got, want) + } + } + + v2 := make([]{{or .QualifiedType .Type}}, N) + arrow.{{.Name}}Traits.Copy(v2, v1) + + if !reflect.DeepEqual(v1, v2) { + t.Fatalf("invalid values:\nv1=%v\nv2=%v\n", v1, v2) + } +} +{{end}} diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/type_traits_timestamp.go b/vendor/github.com/apache/arrow/go/v14/arrow/type_traits_timestamp.go new file mode 100644 index 000000000..7c393b355 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/type_traits_timestamp.go @@ -0,0 +1,59 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package arrow + +import ( + "reflect" + "unsafe" + + "github.com/apache/arrow/go/v14/arrow/endian" +) + +var TimestampTraits timestampTraits + +const ( + // TimestampSizeBytes specifies the number of bytes required to store a single Timestamp in memory + TimestampSizeBytes = int(unsafe.Sizeof(Timestamp(0))) +) + +type timestampTraits struct{} + +// BytesRequired returns the number of bytes required to store n elements in memory. +func (timestampTraits) BytesRequired(n int) int { return TimestampSizeBytes * n } + +func (timestampTraits) PutValue(b []byte, v Timestamp) { + endian.Native.PutUint64(b, uint64(v)) +} + +// CastFromBytes reinterprets the slice b to a slice of type Timestamp. +// +// NOTE: len(b) must be a multiple of TimestampSizeBytes. +func (timestampTraits) CastFromBytes(b []byte) []Timestamp { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*Timestamp)(unsafe.Pointer(h.Data)), cap(b)/TimestampSizeBytes)[:len(b)/TimestampSizeBytes] +} + +// CastToBytes reinterprets the slice b to a slice of bytes. +func (timestampTraits) CastToBytes(b []Timestamp) []byte { + h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + + return unsafe.Slice((*byte)(unsafe.Pointer(h.Data)), cap(b)*TimestampSizeBytes)[:len(b)*TimestampSizeBytes] +} + +// Copy copies src to dst. +func (timestampTraits) Copy(dst, src []Timestamp) { copy(dst, src) } diff --git a/vendor/github.com/apache/arrow/go/v14/arrow/unionmode_string.go b/vendor/github.com/apache/arrow/go/v14/arrow/unionmode_string.go new file mode 100644 index 000000000..394d4f664 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/arrow/unionmode_string.go @@ -0,0 +1,25 @@ +// Code generated by "stringer -type=UnionMode -linecomment"; DO NOT EDIT. + +package arrow + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[SparseMode-2] + _ = x[DenseMode-3] +} + +const _UnionMode_name = "SPARSEDENSE" + +var _UnionMode_index = [...]uint8{0, 6, 11} + +func (i UnionMode) String() string { + i -= 2 + if i < 0 || i >= UnionMode(len(_UnionMode_index)-1) { + return "UnionMode(" + strconv.FormatInt(int64(i+2), 10) + ")" + } + return _UnionMode_name[_UnionMode_index[i]:_UnionMode_index[i+1]] +} diff --git a/vendor/github.com/apache/arrow/go/v14/internal/bitutils/bit_block_counter.go b/vendor/github.com/apache/arrow/go/v14/internal/bitutils/bit_block_counter.go new file mode 100644 index 000000000..86818bfd4 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/bitutils/bit_block_counter.go @@ -0,0 +1,452 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package bitutils + +import ( + "math" + "math/bits" + "unsafe" + + "github.com/apache/arrow/go/v14/arrow/bitutil" + "github.com/apache/arrow/go/v14/internal/utils" +) + +func loadWord(byt []byte) uint64 { + return utils.ToLEUint64(*(*uint64)(unsafe.Pointer(&byt[0]))) +} + +func shiftWord(current, next uint64, shift int64) uint64 { + if shift == 0 { + return current + } + return (current >> shift) | (next << (64 - shift)) +} + +// BitBlockCount is returned by the various bit block counter utilities +// in order to return a length of bits and the population count of that +// slice of bits. +type BitBlockCount struct { + Len int16 + Popcnt int16 +} + +// NoneSet returns true if ALL the bits were 0 in this set, ie: Popcnt == 0 +func (b BitBlockCount) NoneSet() bool { + return b.Popcnt == 0 +} + +// AllSet returns true if ALL the bits were 1 in this set, ie: Popcnt == Len +func (b BitBlockCount) AllSet() bool { + return b.Len == b.Popcnt +} + +// BitBlockCounter is a utility for grabbing chunks of a bitmap at a time and efficiently +// counting the number of bits which are 1. +type BitBlockCounter struct { + bitmap []byte + bitsRemaining int64 + bitOffset int8 +} + +const ( + wordBits int64 = 64 + fourWordsBits int64 = wordBits * 4 +) + +// NewBitBlockCounter returns a BitBlockCounter for the passed bitmap starting at startOffset +// of length nbits. +func NewBitBlockCounter(bitmap []byte, startOffset, nbits int64) *BitBlockCounter { + return &BitBlockCounter{ + bitmap: bitmap[startOffset/8:], + bitsRemaining: nbits, + bitOffset: int8(startOffset % 8), + } +} + +// getBlockSlow is for returning a block of the requested size when there aren't +// enough bits remaining to do a full word computation. +func (b *BitBlockCounter) getBlockSlow(blockSize int64) BitBlockCount { + runlen := int16(utils.Min(b.bitsRemaining, blockSize)) + popcnt := int16(bitutil.CountSetBits(b.bitmap, int(b.bitOffset), int(runlen))) + b.bitsRemaining -= int64(runlen) + b.bitmap = b.bitmap[runlen/8:] + return BitBlockCount{runlen, popcnt} +} + +// NextFourWords returns the next run of available bits, usually 256. The +// returned pair contains the size of run and the number of true values. +// The last block will have a length less than 256 if the bitmap length +// is not a multiple of 256, and will return 0-length blocks in subsequent +// invocations. +func (b *BitBlockCounter) NextFourWords() BitBlockCount { + if b.bitsRemaining == 0 { + return BitBlockCount{0, 0} + } + + totalPopcnt := 0 + if b.bitOffset == 0 { + // if we're aligned at 0 bitoffset, then we can easily just jump from + // word to word nice and easy. + if b.bitsRemaining < fourWordsBits { + return b.getBlockSlow(fourWordsBits) + } + totalPopcnt += bits.OnesCount64(loadWord(b.bitmap)) + totalPopcnt += bits.OnesCount64(loadWord(b.bitmap[8:])) + totalPopcnt += bits.OnesCount64(loadWord(b.bitmap[16:])) + totalPopcnt += bits.OnesCount64(loadWord(b.bitmap[24:])) + } else { + // When the offset is > 0, we need there to be a word beyond the last + // aligned word in the bitmap for the bit shifting logic. + if b.bitsRemaining < 5*fourWordsBits-int64(b.bitOffset) { + return b.getBlockSlow(fourWordsBits) + } + + current := loadWord(b.bitmap) + next := loadWord(b.bitmap[8:]) + totalPopcnt += bits.OnesCount64(shiftWord(current, next, int64(b.bitOffset))) + + current = next + next = loadWord(b.bitmap[16:]) + totalPopcnt += bits.OnesCount64(shiftWord(current, next, int64(b.bitOffset))) + + current = next + next = loadWord(b.bitmap[24:]) + totalPopcnt += bits.OnesCount64(shiftWord(current, next, int64(b.bitOffset))) + + current = next + next = loadWord(b.bitmap[32:]) + totalPopcnt += bits.OnesCount64(shiftWord(current, next, int64(b.bitOffset))) + } + b.bitmap = b.bitmap[bitutil.BytesForBits(fourWordsBits):] + b.bitsRemaining -= fourWordsBits + return BitBlockCount{256, int16(totalPopcnt)} +} + +// NextWord returns the next run of available bits, usually 64. The returned +// pair contains the size of run and the number of true values. The last +// block will have a length less than 64 if the bitmap length is not a +// multiple of 64, and will return 0-length blocks in subsequent +// invocations. +func (b *BitBlockCounter) NextWord() BitBlockCount { + if b.bitsRemaining == 0 { + return BitBlockCount{0, 0} + } + popcnt := 0 + if b.bitOffset == 0 { + if b.bitsRemaining < wordBits { + return b.getBlockSlow(wordBits) + } + popcnt = bits.OnesCount64(loadWord(b.bitmap)) + } else { + // When the offset is > 0, we need there to be a word beyond the last + // aligned word in the bitmap for the bit shifting logic. + if b.bitsRemaining < (2*wordBits - int64(b.bitOffset)) { + return b.getBlockSlow(wordBits) + } + popcnt = bits.OnesCount64(shiftWord(loadWord(b.bitmap), loadWord(b.bitmap[8:]), int64(b.bitOffset))) + } + b.bitmap = b.bitmap[wordBits/8:] + b.bitsRemaining -= wordBits + return BitBlockCount{64, int16(popcnt)} +} + +// OptionalBitBlockCounter is a useful counter to iterate through a possibly +// non-existent validity bitmap to allow us to write one code path for both +// the with-nulls and no-nulls cases without giving up a lot of performance. +type OptionalBitBlockCounter struct { + hasBitmap bool + pos int64 + len int64 + counter *BitBlockCounter +} + +// NewOptionalBitBlockCounter constructs and returns a new bit block counter that +// can properly handle the case when a bitmap is null, if it is guaranteed that the +// the bitmap is not nil, then prefer NewBitBlockCounter here. +func NewOptionalBitBlockCounter(bitmap []byte, offset, length int64) *OptionalBitBlockCounter { + var counter *BitBlockCounter + if bitmap != nil { + counter = NewBitBlockCounter(bitmap, offset, length) + } + return &OptionalBitBlockCounter{ + hasBitmap: bitmap != nil, + pos: 0, + len: length, + counter: counter, + } +} + +// NextBlock returns block count for next word when the bitmap is available otherwise +// return a block with length up to INT16_MAX when there is no validity +// bitmap (so all the referenced values are not null). +func (obc *OptionalBitBlockCounter) NextBlock() BitBlockCount { + const maxBlockSize = math.MaxInt16 + if obc.hasBitmap { + block := obc.counter.NextWord() + obc.pos += int64(block.Len) + return block + } + + blockSize := int16(utils.Min(maxBlockSize, obc.len-obc.pos)) + obc.pos += int64(blockSize) + // all values are non-null + return BitBlockCount{blockSize, blockSize} +} + +// NextWord is like NextBlock, but returns a word-sized block even when there is no +// validity bitmap +func (obc *OptionalBitBlockCounter) NextWord() BitBlockCount { + const wordsize = 64 + if obc.hasBitmap { + block := obc.counter.NextWord() + obc.pos += int64(block.Len) + return block + } + blockSize := int16(utils.Min(wordsize, obc.len-obc.pos)) + obc.pos += int64(blockSize) + // all values are non-null + return BitBlockCount{blockSize, blockSize} +} + +// VisitBitBlocks is a utility for easily iterating through the blocks of bits in a bitmap, +// calling the appropriate visitValid/visitInvalid function as we iterate through the bits. +// visitValid is called with the bitoffset of the valid bit. Don't use this inside a tight +// loop when performance is needed and instead prefer manually constructing these loops +// in that scenario. +func VisitBitBlocks(bitmap []byte, offset, length int64, visitValid func(pos int64), visitInvalid func()) { + counter := NewOptionalBitBlockCounter(bitmap, offset, length) + pos := int64(0) + for pos < length { + block := counter.NextBlock() + if block.AllSet() { + for i := 0; i < int(block.Len); i, pos = i+1, pos+1 { + visitValid(pos) + } + } else if block.NoneSet() { + for i := 0; i < int(block.Len); i, pos = i+1, pos+1 { + visitInvalid() + } + } else { + for i := 0; i < int(block.Len); i, pos = i+1, pos+1 { + if bitutil.BitIsSet(bitmap, int(offset+pos)) { + visitValid(pos) + } else { + visitInvalid() + } + } + } + } +} + +// VisitBitBlocks is a utility for easily iterating through the blocks of bits in a bitmap, +// calling the appropriate visitValid/visitInvalid function as we iterate through the bits. +// visitValid is called with the bitoffset of the valid bit. Don't use this inside a tight +// loop when performance is needed and instead prefer manually constructing these loops +// in that scenario. +func VisitBitBlocksShort(bitmap []byte, offset, length int64, visitValid func(pos int64) error, visitInvalid func() error) error { + counter := NewOptionalBitBlockCounter(bitmap, offset, length) + pos := int64(0) + for pos < length { + block := counter.NextBlock() + if block.AllSet() { + for i := 0; i < int(block.Len); i, pos = i+1, pos+1 { + if err := visitValid(pos); err != nil { + return err + } + } + } else if block.NoneSet() { + for i := 0; i < int(block.Len); i, pos = i+1, pos+1 { + if err := visitInvalid(); err != nil { + return err + } + } + } else { + for i := 0; i < int(block.Len); i, pos = i+1, pos+1 { + if bitutil.BitIsSet(bitmap, int(offset+pos)) { + if err := visitValid(pos); err != nil { + return err + } + } else { + if err := visitInvalid(); err != nil { + return err + } + } + } + } + } + return nil +} + +func VisitTwoBitBlocks(leftBitmap, rightBitmap []byte, leftOffset, rightOffset int64, len int64, visitValid func(pos int64), visitNull func()) { + if leftBitmap == nil || rightBitmap == nil { + // at most one is present + if leftBitmap == nil { + VisitBitBlocks(rightBitmap, rightOffset, len, visitValid, visitNull) + } else { + VisitBitBlocks(leftBitmap, leftOffset, len, visitValid, visitNull) + } + return + } + + bitCounter := NewBinaryBitBlockCounter(leftBitmap, rightBitmap, leftOffset, rightOffset, len) + var pos int64 + for pos < len { + block := bitCounter.NextAndWord() + if block.AllSet() { + for i := 0; i < int(block.Len); i, pos = i+1, pos+1 { + visitValid(pos) + } + } else if block.NoneSet() { + for i := 0; i < int(block.Len); i, pos = i+1, pos+1 { + visitNull() + } + } else { + for i := 0; i < int(block.Len); i, pos = i+1, pos+1 { + if bitutil.BitIsSet(leftBitmap, int(leftOffset+pos)) && bitutil.BitIsSet(rightBitmap, int(rightOffset+pos)) { + visitValid(pos) + } else { + visitNull() + } + } + } + } +} + +type bitOp struct { + bit func(bool, bool) bool + word func(uint64, uint64) uint64 +} + +var ( + bitBlockAnd = bitOp{ + bit: func(a, b bool) bool { return a && b }, + word: func(a, b uint64) uint64 { return a & b }, + } + bitBlockAndNot = bitOp{ + bit: func(a, b bool) bool { return a && !b }, + word: func(a, b uint64) uint64 { return a &^ b }, + } + bitBlockOr = bitOp{ + bit: func(a, b bool) bool { return a || b }, + word: func(a, b uint64) uint64 { return a | b }, + } + bitBlockOrNot = bitOp{ + bit: func(a, b bool) bool { return a || !b }, + word: func(a, b uint64) uint64 { return a | ^b }, + } +) + +// BinaryBitBlockCounter computes popcounts on the result of bitwise +// operations between two bitmaps, 64 bits at a time. A 64-bit word +// is loaded from each bitmap, then the popcount is computed on +// e.g. the bitwise-and of the two words +type BinaryBitBlockCounter struct { + left []byte + right []byte + bitsRemaining int64 + leftOffset, rightOffset int64 + + bitsRequiredForWords int64 +} + +// NewBinaryBitBlockCounter constructs a binary bit block counter for +// computing the popcounts on the results of operations between +// the passed in bitmaps, with their respective offsets. +func NewBinaryBitBlockCounter(left, right []byte, leftOffset, rightOffset int64, length int64) *BinaryBitBlockCounter { + ret := &BinaryBitBlockCounter{ + left: left[leftOffset/8:], + right: right[rightOffset/8:], + leftOffset: leftOffset % 8, + rightOffset: rightOffset % 8, + bitsRemaining: length, + } + + leftBitsReq := int64(64) + if ret.leftOffset != 0 { + leftBitsReq = 64 + (64 - ret.leftOffset) + } + rightBitsReq := int64(64) + if ret.rightOffset != 0 { + rightBitsReq = 64 + (64 - ret.rightOffset) + } + + if leftBitsReq > rightBitsReq { + ret.bitsRequiredForWords = leftBitsReq + } else { + ret.bitsRequiredForWords = rightBitsReq + } + + return ret +} + +// NextAndWord returns the popcount of the bitwise-and of the next run +// of available bits, up to 64. The returned pair contains the size of +// the run and the number of true values. the last block will have a +// length less than 64 if the bitmap length is not a multiple of 64, +// and will return 0-length blocks in subsequent invocations +func (b *BinaryBitBlockCounter) NextAndWord() BitBlockCount { return b.nextWord(bitBlockAnd) } + +// NextAndNotWord is like NextAndWord but performs x &^ y on each run +func (b *BinaryBitBlockCounter) NextAndNotWord() BitBlockCount { return b.nextWord(bitBlockAndNot) } + +// NextOrWord is like NextAndWord but performs x | y on each run +func (b *BinaryBitBlockCounter) NextOrWord() BitBlockCount { return b.nextWord(bitBlockOr) } + +// NextOrWord is like NextAndWord but performs x | ^y on each run +func (b *BinaryBitBlockCounter) NextOrNotWord() BitBlockCount { return b.nextWord(bitBlockOrNot) } + +func (b *BinaryBitBlockCounter) nextWord(op bitOp) BitBlockCount { + if b.bitsRemaining == 0 { + return BitBlockCount{} + } + + // when offset is >0, we need there to be a word beyond the last + // aligned word in the bitmap for the bit shifting logic + if b.bitsRemaining < b.bitsRequiredForWords { + runLength := int16(b.bitsRemaining) + if runLength > int16(wordBits) { + runLength = int16(wordBits) + } + + var popcount int16 + for i := int16(0); i < runLength; i++ { + if op.bit(bitutil.BitIsSet(b.left, int(b.leftOffset)+int(i)), + bitutil.BitIsSet(b.right, int(b.rightOffset)+int(i))) { + popcount++ + } + } + // this code path should trigger _at most_ 2 times. in the "two times" + // case, the first time the run length will be a multiple of 8. + b.left = b.left[runLength/8:] + b.right = b.right[runLength/8:] + b.bitsRemaining -= int64(runLength) + return BitBlockCount{Len: runLength, Popcnt: popcount} + } + + var popcount int + if b.leftOffset == 0 && b.rightOffset == 0 { + popcount = bits.OnesCount64(op.word(loadWord(b.left), loadWord(b.right))) + } else { + leftWord := shiftWord(loadWord(b.left), loadWord(b.left[8:]), b.leftOffset) + rightWord := shiftWord(loadWord(b.right), loadWord(b.right[8:]), b.rightOffset) + popcount = bits.OnesCount64(op.word(leftWord, rightWord)) + } + b.left = b.left[wordBits/8:] + b.right = b.right[wordBits/8:] + b.bitsRemaining -= wordBits + return BitBlockCount{Len: int16(wordBits), Popcnt: int16(popcount)} +} diff --git a/vendor/github.com/apache/arrow/go/v14/internal/bitutils/bit_run_reader.go b/vendor/github.com/apache/arrow/go/v14/internal/bitutils/bit_run_reader.go new file mode 100644 index 000000000..a1686a490 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/bitutils/bit_run_reader.go @@ -0,0 +1,151 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package bitutils + +import ( + "encoding/binary" + "fmt" + "math/bits" + "unsafe" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/bitutil" + "github.com/apache/arrow/go/v14/internal/utils" +) + +// BitRun represents a run of bits with the same value of length Len +// with Set representing if the group of bits were 1 or 0. +type BitRun struct { + Len int64 + Set bool +} + +// BitRunReader is an interface that is usable by multiple callers to provide +// multiple types of bit run readers such as a reverse reader and so on. +// +// It's a convenience interface for counting contiguous set/unset bits in a bitmap. +// In places where BitBlockCounter can be used, then it would be preferred to use that +// as it would be faster than using BitRunReader. +type BitRunReader interface { + NextRun() BitRun +} + +func (b BitRun) String() string { + return fmt.Sprintf("{Length: %d, set=%t}", b.Len, b.Set) +} + +type bitRunReader struct { + bitmap []byte + pos int64 + length int64 + word uint64 + curRunBitSet bool +} + +// NewBitRunReader returns a reader for the given bitmap, offset and length that +// grabs runs of the same value bit at a time for easy iteration. +func NewBitRunReader(bitmap []byte, offset int64, length int64) BitRunReader { + ret := &bitRunReader{ + bitmap: bitmap[offset/8:], + pos: offset % 8, + length: (offset % 8) + length, + } + + if length == 0 { + return ret + } + + ret.curRunBitSet = bitutil.BitIsNotSet(bitmap, int(offset)) + bitsRemaining := length + ret.pos + ret.loadWord(bitsRemaining) + ret.word = ret.word &^ LeastSignificantBitMask(ret.pos) + return ret +} + +// NextRun returns a new BitRun containing the number of contiguous bits with the +// same value. Len == 0 indicates the end of the bitmap. +func (b *bitRunReader) NextRun() BitRun { + if b.pos >= b.length { + return BitRun{0, false} + } + + // This implementation relies on a efficient implementations of + // CountTrailingZeros and assumes that runs are more often then + // not. The logic is to incrementally find the next bit change + // from the current position. This is done by zeroing all + // bits in word_ up to position_ and using the TrailingZeroCount + // to find the index of the next set bit. + + // The runs alternate on each call, so flip the bit. + b.curRunBitSet = !b.curRunBitSet + + start := b.pos + startOffset := start & 63 + + // Invert the word for proper use of CountTrailingZeros and + // clear bits so CountTrailingZeros can do it magic. + b.word = ^b.word &^ LeastSignificantBitMask(startOffset) + + // Go forward until the next change from unset to set. + newbits := int64(bits.TrailingZeros64(b.word)) - startOffset + b.pos += newbits + + if IsMultipleOf64(b.pos) && b.pos < b.length { + b.advanceUntilChange() + } + return BitRun{b.pos - start, b.curRunBitSet} +} + +func (b *bitRunReader) advanceUntilChange() { + newbits := int64(0) + for { + b.bitmap = b.bitmap[arrow.Uint64SizeBytes:] + b.loadNextWord() + newbits = int64(bits.TrailingZeros64(b.word)) + b.pos += newbits + if !IsMultipleOf64(b.pos) || b.pos >= b.length || newbits <= 0 { + break + } + } +} + +func (b *bitRunReader) loadNextWord() { + b.loadWord(b.length - b.pos) +} + +func (b *bitRunReader) loadWord(bitsRemaining int64) { + b.word = 0 + if bitsRemaining >= 64 { + b.word = binary.LittleEndian.Uint64(b.bitmap) + } else { + nbytes := bitutil.BytesForBits(bitsRemaining) + wordptr := (*(*[8]byte)(unsafe.Pointer(&b.word)))[:] + copy(wordptr, b.bitmap[:nbytes]) + + bitutil.SetBitTo(wordptr, int(bitsRemaining), bitutil.BitIsNotSet(wordptr, int(bitsRemaining-1))) + // reset the value to little endian for big endian architectures + b.word = utils.ToLEUint64(b.word) + } + + // Two cases: + // 1. For unset, CountTrailingZeros works naturally so we don't + // invert the word. + // 2. Otherwise invert so we can use CountTrailingZeros. + if b.curRunBitSet { + b.word = ^b.word + } +} diff --git a/vendor/github.com/apache/arrow/go/v14/internal/bitutils/bit_set_run_reader.go b/vendor/github.com/apache/arrow/go/v14/internal/bitutils/bit_set_run_reader.go new file mode 100644 index 000000000..a2269ffec --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/bitutils/bit_set_run_reader.go @@ -0,0 +1,361 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package bitutils + +import ( + "encoding/binary" + "math/bits" + + "github.com/apache/arrow/go/v14/arrow/bitutil" + "github.com/apache/arrow/go/v14/internal/utils" +) + +// IsMultipleOf64 returns whether v is a multiple of 64. +func IsMultipleOf64(v int64) bool { return v&63 == 0 } + +// LeastSignificantBitMask returns a bit mask to return the least significant +// bits for a value starting from the bit index passed in. ie: if you want a +// mask for the 4 least significant bits, you call LeastSignificantBitMask(4) +func LeastSignificantBitMask(index int64) uint64 { + return (uint64(1) << index) - 1 +} + +// SetBitRun describes a run of contiguous set bits in a bitmap with Pos being +// the starting position of the run and Length being the number of bits. +type SetBitRun struct { + Pos int64 + Length int64 +} + +// AtEnd returns true if this bit run is the end of the set by checking +// that the length is 0. +func (s SetBitRun) AtEnd() bool { + return s.Length == 0 +} + +// Equal returns whether rhs is the same run as s +func (s SetBitRun) Equal(rhs SetBitRun) bool { + return s.Pos == rhs.Pos && s.Length == rhs.Length +} + +// SetBitRunReader is an interface for reading groups of contiguous set bits +// from a bitmap. The interface allows us to create different reader implementations +// that share the same interface easily such as a reverse set reader. +type SetBitRunReader interface { + // NextRun will return the next run of contiguous set bits in the bitmap + NextRun() SetBitRun + // Reset allows re-using the reader by providing a new bitmap, offset and length. The arguments + // match the New function for the reader being used. + Reset([]byte, int64, int64) + // VisitSetBitRuns calls visitFn for each set in a loop starting from the current position + // it's roughly equivalent to simply looping, calling NextRun and calling visitFn on the run + // for each run. + VisitSetBitRuns(visitFn VisitFn) error +} + +type baseSetBitRunReader struct { + bitmap []byte + pos int64 + length int64 + remaining int64 + curWord uint64 + curNumBits int32 + reversed bool + + firstBit uint64 +} + +// NewSetBitRunReader returns a SetBitRunReader for the bitmap starting at startOffset which will read +// numvalues bits. +func NewSetBitRunReader(validBits []byte, startOffset, numValues int64) SetBitRunReader { + return newBaseSetBitRunReader(validBits, startOffset, numValues, false) +} + +// NewReverseSetBitRunReader returns a SetBitRunReader like NewSetBitRunReader, except it will +// return runs starting from the end of the bitmap until it reaches startOffset rather than starting +// at startOffset and reading from there. The SetBitRuns will still operate the same, so Pos +// will still be the position of the "left-most" bit of the run or the "start" of the run. It +// just returns runs starting from the end instead of starting from the beginning. +func NewReverseSetBitRunReader(validBits []byte, startOffset, numValues int64) SetBitRunReader { + return newBaseSetBitRunReader(validBits, startOffset, numValues, true) +} + +func newBaseSetBitRunReader(bitmap []byte, startOffset, length int64, reverse bool) *baseSetBitRunReader { + ret := &baseSetBitRunReader{reversed: reverse} + ret.Reset(bitmap, startOffset, length) + return ret +} + +func (br *baseSetBitRunReader) Reset(bitmap []byte, startOffset, length int64) { + br.bitmap = bitmap + br.length = length + br.remaining = length + br.curNumBits = 0 + br.curWord = 0 + + if !br.reversed { + br.pos = startOffset / 8 + br.firstBit = 1 + + bitOffset := int8(startOffset % 8) + if length > 0 && bitOffset != 0 { + br.curNumBits = int32(utils.MinInt(int(length), int(8-bitOffset))) + br.curWord = br.loadPartial(bitOffset, int64(br.curNumBits)) + } + return + } + + br.pos = (startOffset + length) / 8 + br.firstBit = uint64(0x8000000000000000) + endBitOffset := int8((startOffset + length) % 8) + if length > 0 && endBitOffset != 0 { + br.pos++ + br.curNumBits = int32(utils.MinInt(int(length), int(endBitOffset))) + br.curWord = br.loadPartial(8-endBitOffset, int64(br.curNumBits)) + } +} + +func (br *baseSetBitRunReader) consumeBits(word uint64, nbits int32) uint64 { + if br.reversed { + return word << nbits + } + return word >> nbits +} + +func (br *baseSetBitRunReader) countFirstZeros(word uint64) int32 { + if br.reversed { + return int32(bits.LeadingZeros64(word)) + } + return int32(bits.TrailingZeros64(word)) +} + +func (br *baseSetBitRunReader) loadPartial(bitOffset int8, numBits int64) uint64 { + var word [8]byte + nbytes := bitutil.BytesForBits(numBits) + if br.reversed { + br.pos -= nbytes + copy(word[8-nbytes:], br.bitmap[br.pos:br.pos+nbytes]) + return (binary.LittleEndian.Uint64(word[:]) << bitOffset) &^ LeastSignificantBitMask(64-numBits) + } + + copy(word[:], br.bitmap[br.pos:br.pos+nbytes]) + br.pos += nbytes + return (binary.LittleEndian.Uint64(word[:]) >> bitOffset) & LeastSignificantBitMask(numBits) +} + +func (br *baseSetBitRunReader) findCurrentRun() SetBitRun { + nzeros := br.countFirstZeros(br.curWord) + if nzeros >= br.curNumBits { + br.remaining -= int64(br.curNumBits) + br.curWord = 0 + br.curNumBits = 0 + return SetBitRun{0, 0} + } + + br.curWord = br.consumeBits(br.curWord, nzeros) + br.curNumBits -= nzeros + br.remaining -= int64(nzeros) + pos := br.position() + + numOnes := br.countFirstZeros(^br.curWord) + br.curWord = br.consumeBits(br.curWord, numOnes) + br.curNumBits -= numOnes + br.remaining -= int64(numOnes) + return SetBitRun{pos, int64(numOnes)} +} + +func (br *baseSetBitRunReader) position() int64 { + if br.reversed { + return br.remaining + } + return br.length - br.remaining +} + +func (br *baseSetBitRunReader) adjustRun(run SetBitRun) SetBitRun { + if br.reversed { + run.Pos -= run.Length + } + return run +} + +func (br *baseSetBitRunReader) loadFull() (ret uint64) { + if br.reversed { + br.pos -= 8 + } + ret = binary.LittleEndian.Uint64(br.bitmap[br.pos : br.pos+8]) + if !br.reversed { + br.pos += 8 + } + return +} + +func (br *baseSetBitRunReader) skipNextZeros() { + for br.remaining >= 64 { + br.curWord = br.loadFull() + nzeros := br.countFirstZeros(br.curWord) + if nzeros < 64 { + br.curWord = br.consumeBits(br.curWord, nzeros) + br.curNumBits = 64 - nzeros + br.remaining -= int64(nzeros) + return + } + br.remaining -= 64 + } + // run of zeros continues in last bitmap word + if br.remaining > 0 { + br.curWord = br.loadPartial(0, br.remaining) + br.curNumBits = int32(br.remaining) + nzeros := int32(utils.MinInt(int(br.curNumBits), int(br.countFirstZeros(br.curWord)))) + br.curWord = br.consumeBits(br.curWord, nzeros) + br.curNumBits -= nzeros + br.remaining -= int64(nzeros) + } +} + +func (br *baseSetBitRunReader) countNextOnes() int64 { + var length int64 + if ^br.curWord != 0 { + numOnes := br.countFirstZeros(^br.curWord) + br.remaining -= int64(numOnes) + br.curWord = br.consumeBits(br.curWord, numOnes) + br.curNumBits -= numOnes + if br.curNumBits != 0 { + return int64(numOnes) + } + length = int64(numOnes) + } else { + br.remaining -= 64 + br.curNumBits = 0 + length = 64 + } + + for br.remaining >= 64 { + br.curWord = br.loadFull() + numOnes := br.countFirstZeros(^br.curWord) + length += int64(numOnes) + br.remaining -= int64(numOnes) + if numOnes < 64 { + br.curWord = br.consumeBits(br.curWord, numOnes) + br.curNumBits = 64 - numOnes + return length + } + } + + if br.remaining > 0 { + br.curWord = br.loadPartial(0, br.remaining) + br.curNumBits = int32(br.remaining) + numOnes := br.countFirstZeros(^br.curWord) + br.curWord = br.consumeBits(br.curWord, numOnes) + br.curNumBits -= numOnes + br.remaining -= int64(numOnes) + length += int64(numOnes) + } + return length +} + +func (br *baseSetBitRunReader) NextRun() SetBitRun { + var ( + pos int64 = 0 + length int64 = 0 + ) + + if br.curNumBits != 0 { + run := br.findCurrentRun() + if run.Length != 0 && br.curNumBits != 0 { + return br.adjustRun(run) + } + pos = run.Pos + length = run.Length + } + + if length == 0 { + // we didn't get any ones in curWord, so we can skip any zeros + // in the following words + br.skipNextZeros() + if br.remaining == 0 { + return SetBitRun{0, 0} + } + pos = br.position() + } else if br.curNumBits == 0 { + if br.remaining >= 64 { + br.curWord = br.loadFull() + br.curNumBits = 64 + } else if br.remaining > 0 { + br.curWord = br.loadPartial(0, br.remaining) + br.curNumBits = int32(br.remaining) + } else { + return br.adjustRun(SetBitRun{pos, length}) + } + if (br.curWord & br.firstBit) == 0 { + return br.adjustRun(SetBitRun{pos, length}) + } + } + + length += br.countNextOnes() + return br.adjustRun(SetBitRun{pos, length}) +} + +// VisitFn is a callback function for visiting runs of contiguous bits +type VisitFn func(pos int64, length int64) error + +func (br *baseSetBitRunReader) VisitSetBitRuns(visitFn VisitFn) error { + for { + run := br.NextRun() + if run.Length == 0 { + break + } + + if err := visitFn(run.Pos, run.Length); err != nil { + return err + } + } + return nil +} + +// VisitSetBitRuns is just a convenience function for calling NewSetBitRunReader and then VisitSetBitRuns +func VisitSetBitRuns(bitmap []byte, bitmapOffset int64, length int64, visitFn VisitFn) error { + if bitmap == nil { + return visitFn(0, length) + } + rdr := NewSetBitRunReader(bitmap, bitmapOffset, length) + for { + run := rdr.NextRun() + if run.Length == 0 { + break + } + + if err := visitFn(run.Pos, run.Length); err != nil { + return err + } + } + return nil +} + +func VisitSetBitRunsNoErr(bitmap []byte, bitmapOffset int64, length int64, visitFn func(pos, length int64)) { + if bitmap == nil { + visitFn(0, length) + return + } + rdr := NewSetBitRunReader(bitmap, bitmapOffset, length) + for { + run := rdr.NextRun() + if run.Length == 0 { + break + } + visitFn(run.Pos, run.Length) + } +} diff --git a/vendor/github.com/apache/arrow/go/v14/internal/bitutils/bitmap_generate.go b/vendor/github.com/apache/arrow/go/v14/internal/bitutils/bitmap_generate.go new file mode 100644 index 000000000..78219d812 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/bitutils/bitmap_generate.go @@ -0,0 +1,109 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package bitutils + +import "github.com/apache/arrow/go/v14/arrow/bitutil" + +// GenerateBits writes sequential bits to a bitmap. Bits preceding the +// initial start offset are preserved, bits following the bitmap may +// get clobbered. +func GenerateBits(bitmap []byte, start, length int64, g func() bool) { + if length == 0 { + return + } + + cur := bitmap[start/8:] + mask := bitutil.BitMask[start%8] + curbyte := cur[0] & bitutil.PrecedingBitmask[start%8] + + for i := int64(0); i < length; i++ { + bit := g() + if bit { + curbyte = curbyte | mask + } + mask <<= 1 + if mask == 0 { + mask = 1 + cur[0] = curbyte + cur = cur[1:] + curbyte = 0 + } + } + + if mask != 1 { + cur[0] = curbyte + } +} + +// GenerateBitsUnrolled is like GenerateBits but unrolls its main loop for +// higher performance. +// +// See the benchmarks for evidence. +func GenerateBitsUnrolled(bitmap []byte, start, length int64, g func() bool) { + if length == 0 { + return + } + + var ( + curbyte byte + cur = bitmap[start/8:] + startBitOffset uint64 = uint64(start % 8) + mask = bitutil.BitMask[startBitOffset] + remaining = length + ) + + if mask != 0x01 { + curbyte = cur[0] & bitutil.PrecedingBitmask[startBitOffset] + for mask != 0 && remaining > 0 { + if g() { + curbyte |= mask + } + mask <<= 1 + remaining-- + } + cur[0] = curbyte + cur = cur[1:] + } + + var outResults [8]byte + for remainingBytes := remaining / 8; remainingBytes > 0; remainingBytes-- { + for i := 0; i < 8; i++ { + if g() { + outResults[i] = 1 + } else { + outResults[i] = 0 + } + } + cur[0] = (outResults[0] | outResults[1]<<1 | outResults[2]<<2 | + outResults[3]<<3 | outResults[4]<<4 | outResults[5]<<5 | + outResults[6]<<6 | outResults[7]<<7) + cur = cur[1:] + } + + remainingBits := remaining % 8 + if remainingBits > 0 { + curbyte = 0 + mask = 0x01 + for ; remainingBits > 0; remainingBits-- { + if g() { + curbyte |= mask + } + mask <<= 1 + } + cur[0] = curbyte + } +} diff --git a/vendor/github.com/apache/arrow/go/v14/internal/hashing/hash_funcs.go b/vendor/github.com/apache/arrow/go/v14/internal/hashing/hash_funcs.go new file mode 100644 index 000000000..c1bdfeb6d --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/hashing/hash_funcs.go @@ -0,0 +1,90 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package hashing + +import ( + "math/bits" + "unsafe" + + "github.com/zeebo/xxh3" +) + +func hashInt(val uint64, alg uint64) uint64 { + // Two of xxhash's prime multipliers (which are chosen for their + // bit dispersion properties) + var multipliers = [2]uint64{11400714785074694791, 14029467366897019727} + // Multiplying by the prime number mixes the low bits into the high bits, + // then byte-swapping (which is a single CPU instruction) allows the + // combined high and low bits to participate in the initial hash table index. + return bits.ReverseBytes64(multipliers[alg] * val) +} + +func hashFloat32(val float32, alg uint64) uint64 { + // grab the raw byte pattern of the + bt := *(*[4]byte)(unsafe.Pointer(&val)) + x := uint64(*(*uint32)(unsafe.Pointer(&bt[0]))) + hx := hashInt(x, alg) + hy := hashInt(x, alg^1) + return 4 ^ hx ^ hy +} + +func hashFloat64(val float64, alg uint64) uint64 { + bt := *(*[8]byte)(unsafe.Pointer(&val)) + hx := hashInt(uint64(*(*uint32)(unsafe.Pointer(&bt[4]))), alg) + hy := hashInt(uint64(*(*uint32)(unsafe.Pointer(&bt[0]))), alg^1) + return 8 ^ hx ^ hy +} + +// prime constants used for slightly increasing the hash quality further +var exprimes = [2]uint64{1609587929392839161, 9650029242287828579} + +// for smaller amounts of bytes this is faster than even calling into +// xxh3 to do the Hash, so we specialize in order to get the benefits +// of that performance. +func Hash(b []byte, alg uint64) uint64 { + n := uint32(len(b)) + if n <= 16 { + switch { + case n > 8: + // 8 < length <= 16 + // apply same principle as above, but as two 64-bit ints + x := *(*uint64)(unsafe.Pointer(&b[n-8])) + y := *(*uint64)(unsafe.Pointer(&b[0])) + hx := hashInt(x, alg) + hy := hashInt(y, alg^1) + return uint64(n) ^ hx ^ hy + case n >= 4: + // 4 < length <= 8 + // we can read the bytes as two overlapping 32-bit ints, apply different + // hash functions to each in parallel + // then xor the results + x := *(*uint32)(unsafe.Pointer(&b[n-4])) + y := *(*uint32)(unsafe.Pointer(&b[0])) + hx := hashInt(uint64(x), alg) + hy := hashInt(uint64(y), alg^1) + return uint64(n) ^ hx ^ hy + case n > 0: + x := uint32((n << 24) ^ (uint32(b[0]) << 16) ^ (uint32(b[n/2]) << 8) ^ uint32(b[n-1])) + return hashInt(uint64(x), alg) + case n == 0: + return 1 + } + } + + // increase differentiation enough to improve hash quality + return xxh3.Hash(b) + exprimes[alg] +} diff --git a/vendor/github.com/apache/arrow/go/v14/internal/hashing/hash_string.go b/vendor/github.com/apache/arrow/go/v14/internal/hashing/hash_string.go new file mode 100644 index 000000000..b772c7d7f --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/hashing/hash_string.go @@ -0,0 +1,26 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build go1.20 || tinygo + +package hashing + +import "unsafe" + +func hashString(val string, alg uint64) uint64 { + buf := unsafe.Slice(unsafe.StringData(val), len(val)) + return Hash(buf, alg) +} diff --git a/vendor/github.com/apache/arrow/go/v14/internal/hashing/hash_string_go1.19.go b/vendor/github.com/apache/arrow/go/v14/internal/hashing/hash_string_go1.19.go new file mode 100644 index 000000000..f38eb5c52 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/hashing/hash_string_go1.19.go @@ -0,0 +1,37 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !go1.20 && !tinygo + +package hashing + +import ( + "reflect" + "unsafe" +) + +func hashString(val string, alg uint64) uint64 { + if val == "" { + return Hash([]byte{}, alg) + } + // highly efficient way to get byte slice without copy before + // the introduction of unsafe.StringData in go1.20 + // (https://stackoverflow.com/questions/59209493/how-to-use-unsafe-get-a-byte-slice-from-a-string-without-memory-copy) + const MaxInt32 = 1<<31 - 1 + buf := (*[MaxInt32]byte)(unsafe.Pointer((*reflect.StringHeader)( + unsafe.Pointer(&val)).Data))[: len(val)&MaxInt32 : len(val)&MaxInt32] + return Hash(buf, alg) +} diff --git a/vendor/github.com/apache/arrow/go/v14/internal/hashing/types.tmpldata b/vendor/github.com/apache/arrow/go/v14/internal/hashing/types.tmpldata new file mode 100644 index 000000000..0ba6f765d --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/hashing/types.tmpldata @@ -0,0 +1,42 @@ +[ + { + "Name": "Int8", + "name": "int8" + }, + { + "Name": "Uint8", + "name": "uint8" + }, + { + "Name": "Int16", + "name": "int16" + }, + { + "Name": "Uint16", + "name": "uint16" + }, + { + "Name": "Int32", + "name": "int32" + }, + { + "Name": "Int64", + "name": "int64" + }, + { + "Name": "Uint32", + "name": "uint32" + }, + { + "Name": "Uint64", + "name": "uint64" + }, + { + "Name": "Float32", + "name": "float32" + }, + { + "Name": "Float64", + "name": "float64" + } +] diff --git a/vendor/github.com/apache/arrow/go/v14/internal/hashing/xxh3_memo_table.gen.go b/vendor/github.com/apache/arrow/go/v14/internal/hashing/xxh3_memo_table.gen.go new file mode 100644 index 000000000..cc996552b --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/hashing/xxh3_memo_table.gen.go @@ -0,0 +1,2833 @@ +// Code generated by xxh3_memo_table.gen.go.tmpl. DO NOT EDIT. + +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package hashing + +import ( + "math" + + "github.com/apache/arrow/go/v14/arrow" + "github.com/apache/arrow/go/v14/arrow/bitutil" + "github.com/apache/arrow/go/v14/internal/utils" +) + +type payloadInt8 struct { + val int8 + memoIdx int32 +} + +type entryInt8 struct { + h uint64 + payload payloadInt8 +} + +func (e entryInt8) Valid() bool { return e.h != sentinel } + +// Int8HashTable is a hashtable specifically for int8 that +// is utilized with the MemoTable to generalize interactions for easier +// implementation of dictionaries without losing performance. +type Int8HashTable struct { + cap uint64 + capMask uint64 + size uint64 + + entries []entryInt8 +} + +// NewInt8HashTable returns a new hash table for int8 values +// initialized with the passed in capacity or 32 whichever is larger. +func NewInt8HashTable(cap uint64) *Int8HashTable { + initCap := uint64(bitutil.NextPowerOf2(int(max(cap, 32)))) + ret := &Int8HashTable{cap: initCap, capMask: initCap - 1, size: 0} + ret.entries = make([]entryInt8, initCap) + return ret +} + +// Reset drops all of the values in this hash table and re-initializes it +// with the specified initial capacity as if by calling New, but without having +// to reallocate the object. +func (h *Int8HashTable) Reset(cap uint64) { + h.cap = uint64(bitutil.NextPowerOf2(int(max(cap, 32)))) + h.capMask = h.cap - 1 + h.size = 0 + h.entries = make([]entryInt8, h.cap) +} + +// CopyValues is used for copying the values out of the hash table into the +// passed in slice, in the order that they were first inserted +func (h *Int8HashTable) CopyValues(out []int8) { + h.CopyValuesSubset(0, out) +} + +// CopyValuesSubset copies a subset of the values in the hashtable out, starting +// with the value at start, in the order that they were inserted. +func (h *Int8HashTable) CopyValuesSubset(start int, out []int8) { + h.VisitEntries(func(e *entryInt8) { + idx := e.payload.memoIdx - int32(start) + if idx >= 0 { + out[idx] = e.payload.val + } + }) +} + +func (h *Int8HashTable) WriteOut(out []byte) { + h.WriteOutSubset(0, out) +} + +func (h *Int8HashTable) WriteOutSubset(start int, out []byte) { + data := arrow.Int8Traits.CastFromBytes(out) + h.VisitEntries(func(e *entryInt8) { + idx := e.payload.memoIdx - int32(start) + if idx >= 0 { + data[idx] = e.payload.val + } + }) +} + +func (h *Int8HashTable) needUpsize() bool { return h.size*uint64(loadFactor) >= h.cap } + +func (Int8HashTable) fixHash(v uint64) uint64 { + if v == sentinel { + return 42 + } + return v +} + +// Lookup retrieves the entry for a given hash value assuming it's payload value returns +// true when passed to the cmp func. Returns a pointer to the entry for the given hash value, +// and a boolean as to whether it was found. It is not safe to use the pointer if the bool is false. +func (h *Int8HashTable) Lookup(v uint64, cmp func(int8) bool) (*entryInt8, bool) { + idx, ok := h.lookup(v, h.capMask, cmp) + return &h.entries[idx], ok +} + +func (h *Int8HashTable) lookup(v uint64, szMask uint64, cmp func(int8) bool) (uint64, bool) { + const perturbShift uint8 = 5 + + var ( + idx uint64 + perturb uint64 + e *entryInt8 + ) + + v = h.fixHash(v) + idx = v & szMask + perturb = (v >> uint64(perturbShift)) + 1 + + for { + e = &h.entries[idx] + if e.h == v && cmp(e.payload.val) { + return idx, true + } + + if e.h == sentinel { + return idx, false + } + + // perturbation logic inspired from CPython's set/dict object + // the goal is that all 64 bits of unmasked hash value eventually + // participate int he probing sequence, to minimize clustering + idx = (idx + perturb) & szMask + perturb = (perturb >> uint64(perturbShift)) + 1 + } +} + +func (h *Int8HashTable) upsize(newcap uint64) error { + newMask := newcap - 1 + + oldEntries := h.entries + h.entries = make([]entryInt8, newcap) + for _, e := range oldEntries { + if e.Valid() { + idx, _ := h.lookup(e.h, newMask, func(int8) bool { return false }) + h.entries[idx] = e + } + } + h.cap = newcap + h.capMask = newMask + return nil +} + +// Insert updates the given entry with the provided hash value, payload value and memo index. +// The entry pointer must have been retrieved via lookup in order to actually insert properly. +func (h *Int8HashTable) Insert(e *entryInt8, v uint64, val int8, memoIdx int32) error { + e.h = h.fixHash(v) + e.payload.val = val + e.payload.memoIdx = memoIdx + h.size++ + + if h.needUpsize() { + h.upsize(h.cap * uint64(loadFactor) * 2) + } + return nil +} + +// VisitEntries will call the passed in function on each *valid* entry in the hash table, +// a valid entry being one which has had a value inserted into it. +func (h *Int8HashTable) VisitEntries(visit func(*entryInt8)) { + for _, e := range h.entries { + if e.Valid() { + visit(&e) + } + } +} + +// Int8MemoTable is a wrapper over the appropriate hashtable to provide an interface +// conforming to the MemoTable interface defined in the encoding package for general interactions +// regarding dictionaries. +type Int8MemoTable struct { + tbl *Int8HashTable + nullIdx int32 +} + +// NewInt8MemoTable returns a new memotable with num entries pre-allocated to reduce further +// allocations when inserting. +func NewInt8MemoTable(num int64) *Int8MemoTable { + return &Int8MemoTable{tbl: NewInt8HashTable(uint64(num)), nullIdx: KeyNotFound} +} + +func (Int8MemoTable) TypeTraits() TypeTraits { + return arrow.Int8Traits +} + +// Reset allows this table to be re-used by dumping all the data currently in the table. +func (s *Int8MemoTable) Reset() { + s.tbl.Reset(32) + s.nullIdx = KeyNotFound +} + +// Size returns the current number of inserted elements into the table including if a null +// has been inserted. +func (s *Int8MemoTable) Size() int { + sz := int(s.tbl.size) + if _, ok := s.GetNull(); ok { + sz++ + } + return sz +} + +// GetNull returns the index of an inserted null or KeyNotFound along with a bool +// that will be true if found and false if not. +func (s *Int8MemoTable) GetNull() (int, bool) { + return int(s.nullIdx), s.nullIdx != KeyNotFound +} + +// GetOrInsertNull will return the index of the null entry or insert a null entry +// if one currently doesn't exist. The found value will be true if there was already +// a null in the table, and false if it inserted one. +func (s *Int8MemoTable) GetOrInsertNull() (idx int, found bool) { + idx, found = s.GetNull() + if !found { + idx = s.Size() + s.nullIdx = int32(idx) + } + return +} + +// CopyValues will copy the values from the memo table out into the passed in slice +// which must be of the appropriate type. +func (s *Int8MemoTable) CopyValues(out interface{}) { + s.CopyValuesSubset(0, out) +} + +// CopyValuesSubset is like CopyValues but only copies a subset of values starting +// at the provided start index +func (s *Int8MemoTable) CopyValuesSubset(start int, out interface{}) { + s.tbl.CopyValuesSubset(start, out.([]int8)) +} + +func (s *Int8MemoTable) WriteOut(out []byte) { + s.tbl.CopyValues(arrow.Int8Traits.CastFromBytes(out)) +} + +func (s *Int8MemoTable) WriteOutSubset(start int, out []byte) { + s.tbl.CopyValuesSubset(start, arrow.Int8Traits.CastFromBytes(out)) +} + +func (s *Int8MemoTable) WriteOutLE(out []byte) { + s.tbl.WriteOut(out) +} + +func (s *Int8MemoTable) WriteOutSubsetLE(start int, out []byte) { + s.tbl.WriteOutSubset(start, out) +} + +// Get returns the index of the requested value in the hash table or KeyNotFound +// along with a boolean indicating if it was found or not. +func (s *Int8MemoTable) Get(val interface{}) (int, bool) { + + h := hashInt(uint64(val.(int8)), 0) + if e, ok := s.tbl.Lookup(h, func(v int8) bool { return val.(int8) == v }); ok { + return int(e.payload.memoIdx), ok + } + return KeyNotFound, false +} + +// GetOrInsert will return the index of the specified value in the table, or insert the +// value into the table and return the new index. found indicates whether or not it already +// existed in the table (true) or was inserted by this call (false). +func (s *Int8MemoTable) GetOrInsert(val interface{}) (idx int, found bool, err error) { + + h := hashInt(uint64(val.(int8)), 0) + e, ok := s.tbl.Lookup(h, func(v int8) bool { + return val.(int8) == v + }) + + if ok { + idx = int(e.payload.memoIdx) + found = true + } else { + idx = s.Size() + s.tbl.Insert(e, h, val.(int8), int32(idx)) + } + return +} + +// GetOrInsertBytes is unimplemented +func (s *Int8MemoTable) GetOrInsertBytes(val []byte) (idx int, found bool, err error) { + panic("unimplemented") +} + +type payloadUint8 struct { + val uint8 + memoIdx int32 +} + +type entryUint8 struct { + h uint64 + payload payloadUint8 +} + +func (e entryUint8) Valid() bool { return e.h != sentinel } + +// Uint8HashTable is a hashtable specifically for uint8 that +// is utilized with the MemoTable to generalize interactions for easier +// implementation of dictionaries without losing performance. +type Uint8HashTable struct { + cap uint64 + capMask uint64 + size uint64 + + entries []entryUint8 +} + +// NewUint8HashTable returns a new hash table for uint8 values +// initialized with the passed in capacity or 32 whichever is larger. +func NewUint8HashTable(cap uint64) *Uint8HashTable { + initCap := uint64(bitutil.NextPowerOf2(int(max(cap, 32)))) + ret := &Uint8HashTable{cap: initCap, capMask: initCap - 1, size: 0} + ret.entries = make([]entryUint8, initCap) + return ret +} + +// Reset drops all of the values in this hash table and re-initializes it +// with the specified initial capacity as if by calling New, but without having +// to reallocate the object. +func (h *Uint8HashTable) Reset(cap uint64) { + h.cap = uint64(bitutil.NextPowerOf2(int(max(cap, 32)))) + h.capMask = h.cap - 1 + h.size = 0 + h.entries = make([]entryUint8, h.cap) +} + +// CopyValues is used for copying the values out of the hash table into the +// passed in slice, in the order that they were first inserted +func (h *Uint8HashTable) CopyValues(out []uint8) { + h.CopyValuesSubset(0, out) +} + +// CopyValuesSubset copies a subset of the values in the hashtable out, starting +// with the value at start, in the order that they were inserted. +func (h *Uint8HashTable) CopyValuesSubset(start int, out []uint8) { + h.VisitEntries(func(e *entryUint8) { + idx := e.payload.memoIdx - int32(start) + if idx >= 0 { + out[idx] = e.payload.val + } + }) +} + +func (h *Uint8HashTable) WriteOut(out []byte) { + h.WriteOutSubset(0, out) +} + +func (h *Uint8HashTable) WriteOutSubset(start int, out []byte) { + data := arrow.Uint8Traits.CastFromBytes(out) + h.VisitEntries(func(e *entryUint8) { + idx := e.payload.memoIdx - int32(start) + if idx >= 0 { + data[idx] = e.payload.val + } + }) +} + +func (h *Uint8HashTable) needUpsize() bool { return h.size*uint64(loadFactor) >= h.cap } + +func (Uint8HashTable) fixHash(v uint64) uint64 { + if v == sentinel { + return 42 + } + return v +} + +// Lookup retrieves the entry for a given hash value assuming it's payload value returns +// true when passed to the cmp func. Returns a pointer to the entry for the given hash value, +// and a boolean as to whether it was found. It is not safe to use the pointer if the bool is false. +func (h *Uint8HashTable) Lookup(v uint64, cmp func(uint8) bool) (*entryUint8, bool) { + idx, ok := h.lookup(v, h.capMask, cmp) + return &h.entries[idx], ok +} + +func (h *Uint8HashTable) lookup(v uint64, szMask uint64, cmp func(uint8) bool) (uint64, bool) { + const perturbShift uint8 = 5 + + var ( + idx uint64 + perturb uint64 + e *entryUint8 + ) + + v = h.fixHash(v) + idx = v & szMask + perturb = (v >> uint64(perturbShift)) + 1 + + for { + e = &h.entries[idx] + if e.h == v && cmp(e.payload.val) { + return idx, true + } + + if e.h == sentinel { + return idx, false + } + + // perturbation logic inspired from CPython's set/dict object + // the goal is that all 64 bits of unmasked hash value eventually + // participate int he probing sequence, to minimize clustering + idx = (idx + perturb) & szMask + perturb = (perturb >> uint64(perturbShift)) + 1 + } +} + +func (h *Uint8HashTable) upsize(newcap uint64) error { + newMask := newcap - 1 + + oldEntries := h.entries + h.entries = make([]entryUint8, newcap) + for _, e := range oldEntries { + if e.Valid() { + idx, _ := h.lookup(e.h, newMask, func(uint8) bool { return false }) + h.entries[idx] = e + } + } + h.cap = newcap + h.capMask = newMask + return nil +} + +// Insert updates the given entry with the provided hash value, payload value and memo index. +// The entry pointer must have been retrieved via lookup in order to actually insert properly. +func (h *Uint8HashTable) Insert(e *entryUint8, v uint64, val uint8, memoIdx int32) error { + e.h = h.fixHash(v) + e.payload.val = val + e.payload.memoIdx = memoIdx + h.size++ + + if h.needUpsize() { + h.upsize(h.cap * uint64(loadFactor) * 2) + } + return nil +} + +// VisitEntries will call the passed in function on each *valid* entry in the hash table, +// a valid entry being one which has had a value inserted into it. +func (h *Uint8HashTable) VisitEntries(visit func(*entryUint8)) { + for _, e := range h.entries { + if e.Valid() { + visit(&e) + } + } +} + +// Uint8MemoTable is a wrapper over the appropriate hashtable to provide an interface +// conforming to the MemoTable interface defined in the encoding package for general interactions +// regarding dictionaries. +type Uint8MemoTable struct { + tbl *Uint8HashTable + nullIdx int32 +} + +// NewUint8MemoTable returns a new memotable with num entries pre-allocated to reduce further +// allocations when inserting. +func NewUint8MemoTable(num int64) *Uint8MemoTable { + return &Uint8MemoTable{tbl: NewUint8HashTable(uint64(num)), nullIdx: KeyNotFound} +} + +func (Uint8MemoTable) TypeTraits() TypeTraits { + return arrow.Uint8Traits +} + +// Reset allows this table to be re-used by dumping all the data currently in the table. +func (s *Uint8MemoTable) Reset() { + s.tbl.Reset(32) + s.nullIdx = KeyNotFound +} + +// Size returns the current number of inserted elements into the table including if a null +// has been inserted. +func (s *Uint8MemoTable) Size() int { + sz := int(s.tbl.size) + if _, ok := s.GetNull(); ok { + sz++ + } + return sz +} + +// GetNull returns the index of an inserted null or KeyNotFound along with a bool +// that will be true if found and false if not. +func (s *Uint8MemoTable) GetNull() (int, bool) { + return int(s.nullIdx), s.nullIdx != KeyNotFound +} + +// GetOrInsertNull will return the index of the null entry or insert a null entry +// if one currently doesn't exist. The found value will be true if there was already +// a null in the table, and false if it inserted one. +func (s *Uint8MemoTable) GetOrInsertNull() (idx int, found bool) { + idx, found = s.GetNull() + if !found { + idx = s.Size() + s.nullIdx = int32(idx) + } + return +} + +// CopyValues will copy the values from the memo table out into the passed in slice +// which must be of the appropriate type. +func (s *Uint8MemoTable) CopyValues(out interface{}) { + s.CopyValuesSubset(0, out) +} + +// CopyValuesSubset is like CopyValues but only copies a subset of values starting +// at the provided start index +func (s *Uint8MemoTable) CopyValuesSubset(start int, out interface{}) { + s.tbl.CopyValuesSubset(start, out.([]uint8)) +} + +func (s *Uint8MemoTable) WriteOut(out []byte) { + s.tbl.CopyValues(arrow.Uint8Traits.CastFromBytes(out)) +} + +func (s *Uint8MemoTable) WriteOutSubset(start int, out []byte) { + s.tbl.CopyValuesSubset(start, arrow.Uint8Traits.CastFromBytes(out)) +} + +func (s *Uint8MemoTable) WriteOutLE(out []byte) { + s.tbl.WriteOut(out) +} + +func (s *Uint8MemoTable) WriteOutSubsetLE(start int, out []byte) { + s.tbl.WriteOutSubset(start, out) +} + +// Get returns the index of the requested value in the hash table or KeyNotFound +// along with a boolean indicating if it was found or not. +func (s *Uint8MemoTable) Get(val interface{}) (int, bool) { + + h := hashInt(uint64(val.(uint8)), 0) + if e, ok := s.tbl.Lookup(h, func(v uint8) bool { return val.(uint8) == v }); ok { + return int(e.payload.memoIdx), ok + } + return KeyNotFound, false +} + +// GetOrInsert will return the index of the specified value in the table, or insert the +// value into the table and return the new index. found indicates whether or not it already +// existed in the table (true) or was inserted by this call (false). +func (s *Uint8MemoTable) GetOrInsert(val interface{}) (idx int, found bool, err error) { + + h := hashInt(uint64(val.(uint8)), 0) + e, ok := s.tbl.Lookup(h, func(v uint8) bool { + return val.(uint8) == v + }) + + if ok { + idx = int(e.payload.memoIdx) + found = true + } else { + idx = s.Size() + s.tbl.Insert(e, h, val.(uint8), int32(idx)) + } + return +} + +// GetOrInsertBytes is unimplemented +func (s *Uint8MemoTable) GetOrInsertBytes(val []byte) (idx int, found bool, err error) { + panic("unimplemented") +} + +type payloadInt16 struct { + val int16 + memoIdx int32 +} + +type entryInt16 struct { + h uint64 + payload payloadInt16 +} + +func (e entryInt16) Valid() bool { return e.h != sentinel } + +// Int16HashTable is a hashtable specifically for int16 that +// is utilized with the MemoTable to generalize interactions for easier +// implementation of dictionaries without losing performance. +type Int16HashTable struct { + cap uint64 + capMask uint64 + size uint64 + + entries []entryInt16 +} + +// NewInt16HashTable returns a new hash table for int16 values +// initialized with the passed in capacity or 32 whichever is larger. +func NewInt16HashTable(cap uint64) *Int16HashTable { + initCap := uint64(bitutil.NextPowerOf2(int(max(cap, 32)))) + ret := &Int16HashTable{cap: initCap, capMask: initCap - 1, size: 0} + ret.entries = make([]entryInt16, initCap) + return ret +} + +// Reset drops all of the values in this hash table and re-initializes it +// with the specified initial capacity as if by calling New, but without having +// to reallocate the object. +func (h *Int16HashTable) Reset(cap uint64) { + h.cap = uint64(bitutil.NextPowerOf2(int(max(cap, 32)))) + h.capMask = h.cap - 1 + h.size = 0 + h.entries = make([]entryInt16, h.cap) +} + +// CopyValues is used for copying the values out of the hash table into the +// passed in slice, in the order that they were first inserted +func (h *Int16HashTable) CopyValues(out []int16) { + h.CopyValuesSubset(0, out) +} + +// CopyValuesSubset copies a subset of the values in the hashtable out, starting +// with the value at start, in the order that they were inserted. +func (h *Int16HashTable) CopyValuesSubset(start int, out []int16) { + h.VisitEntries(func(e *entryInt16) { + idx := e.payload.memoIdx - int32(start) + if idx >= 0 { + out[idx] = e.payload.val + } + }) +} + +func (h *Int16HashTable) WriteOut(out []byte) { + h.WriteOutSubset(0, out) +} + +func (h *Int16HashTable) WriteOutSubset(start int, out []byte) { + data := arrow.Int16Traits.CastFromBytes(out) + h.VisitEntries(func(e *entryInt16) { + idx := e.payload.memoIdx - int32(start) + if idx >= 0 { + data[idx] = utils.ToLEInt16(e.payload.val) + } + }) +} + +func (h *Int16HashTable) needUpsize() bool { return h.size*uint64(loadFactor) >= h.cap } + +func (Int16HashTable) fixHash(v uint64) uint64 { + if v == sentinel { + return 42 + } + return v +} + +// Lookup retrieves the entry for a given hash value assuming it's payload value returns +// true when passed to the cmp func. Returns a pointer to the entry for the given hash value, +// and a boolean as to whether it was found. It is not safe to use the pointer if the bool is false. +func (h *Int16HashTable) Lookup(v uint64, cmp func(int16) bool) (*entryInt16, bool) { + idx, ok := h.lookup(v, h.capMask, cmp) + return &h.entries[idx], ok +} + +func (h *Int16HashTable) lookup(v uint64, szMask uint64, cmp func(int16) bool) (uint64, bool) { + const perturbShift uint8 = 5 + + var ( + idx uint64 + perturb uint64 + e *entryInt16 + ) + + v = h.fixHash(v) + idx = v & szMask + perturb = (v >> uint64(perturbShift)) + 1 + + for { + e = &h.entries[idx] + if e.h == v && cmp(e.payload.val) { + return idx, true + } + + if e.h == sentinel { + return idx, false + } + + // perturbation logic inspired from CPython's set/dict object + // the goal is that all 64 bits of unmasked hash value eventually + // participate int he probing sequence, to minimize clustering + idx = (idx + perturb) & szMask + perturb = (perturb >> uint64(perturbShift)) + 1 + } +} + +func (h *Int16HashTable) upsize(newcap uint64) error { + newMask := newcap - 1 + + oldEntries := h.entries + h.entries = make([]entryInt16, newcap) + for _, e := range oldEntries { + if e.Valid() { + idx, _ := h.lookup(e.h, newMask, func(int16) bool { return false }) + h.entries[idx] = e + } + } + h.cap = newcap + h.capMask = newMask + return nil +} + +// Insert updates the given entry with the provided hash value, payload value and memo index. +// The entry pointer must have been retrieved via lookup in order to actually insert properly. +func (h *Int16HashTable) Insert(e *entryInt16, v uint64, val int16, memoIdx int32) error { + e.h = h.fixHash(v) + e.payload.val = val + e.payload.memoIdx = memoIdx + h.size++ + + if h.needUpsize() { + h.upsize(h.cap * uint64(loadFactor) * 2) + } + return nil +} + +// VisitEntries will call the passed in function on each *valid* entry in the hash table, +// a valid entry being one which has had a value inserted into it. +func (h *Int16HashTable) VisitEntries(visit func(*entryInt16)) { + for _, e := range h.entries { + if e.Valid() { + visit(&e) + } + } +} + +// Int16MemoTable is a wrapper over the appropriate hashtable to provide an interface +// conforming to the MemoTable interface defined in the encoding package for general interactions +// regarding dictionaries. +type Int16MemoTable struct { + tbl *Int16HashTable + nullIdx int32 +} + +// NewInt16MemoTable returns a new memotable with num entries pre-allocated to reduce further +// allocations when inserting. +func NewInt16MemoTable(num int64) *Int16MemoTable { + return &Int16MemoTable{tbl: NewInt16HashTable(uint64(num)), nullIdx: KeyNotFound} +} + +func (Int16MemoTable) TypeTraits() TypeTraits { + return arrow.Int16Traits +} + +// Reset allows this table to be re-used by dumping all the data currently in the table. +func (s *Int16MemoTable) Reset() { + s.tbl.Reset(32) + s.nullIdx = KeyNotFound +} + +// Size returns the current number of inserted elements into the table including if a null +// has been inserted. +func (s *Int16MemoTable) Size() int { + sz := int(s.tbl.size) + if _, ok := s.GetNull(); ok { + sz++ + } + return sz +} + +// GetNull returns the index of an inserted null or KeyNotFound along with a bool +// that will be true if found and false if not. +func (s *Int16MemoTable) GetNull() (int, bool) { + return int(s.nullIdx), s.nullIdx != KeyNotFound +} + +// GetOrInsertNull will return the index of the null entry or insert a null entry +// if one currently doesn't exist. The found value will be true if there was already +// a null in the table, and false if it inserted one. +func (s *Int16MemoTable) GetOrInsertNull() (idx int, found bool) { + idx, found = s.GetNull() + if !found { + idx = s.Size() + s.nullIdx = int32(idx) + } + return +} + +// CopyValues will copy the values from the memo table out into the passed in slice +// which must be of the appropriate type. +func (s *Int16MemoTable) CopyValues(out interface{}) { + s.CopyValuesSubset(0, out) +} + +// CopyValuesSubset is like CopyValues but only copies a subset of values starting +// at the provided start index +func (s *Int16MemoTable) CopyValuesSubset(start int, out interface{}) { + s.tbl.CopyValuesSubset(start, out.([]int16)) +} + +func (s *Int16MemoTable) WriteOut(out []byte) { + s.tbl.CopyValues(arrow.Int16Traits.CastFromBytes(out)) +} + +func (s *Int16MemoTable) WriteOutSubset(start int, out []byte) { + s.tbl.CopyValuesSubset(start, arrow.Int16Traits.CastFromBytes(out)) +} + +func (s *Int16MemoTable) WriteOutLE(out []byte) { + s.tbl.WriteOut(out) +} + +func (s *Int16MemoTable) WriteOutSubsetLE(start int, out []byte) { + s.tbl.WriteOutSubset(start, out) +} + +// Get returns the index of the requested value in the hash table or KeyNotFound +// along with a boolean indicating if it was found or not. +func (s *Int16MemoTable) Get(val interface{}) (int, bool) { + + h := hashInt(uint64(val.(int16)), 0) + if e, ok := s.tbl.Lookup(h, func(v int16) bool { return val.(int16) == v }); ok { + return int(e.payload.memoIdx), ok + } + return KeyNotFound, false +} + +// GetOrInsert will return the index of the specified value in the table, or insert the +// value into the table and return the new index. found indicates whether or not it already +// existed in the table (true) or was inserted by this call (false). +func (s *Int16MemoTable) GetOrInsert(val interface{}) (idx int, found bool, err error) { + + h := hashInt(uint64(val.(int16)), 0) + e, ok := s.tbl.Lookup(h, func(v int16) bool { + return val.(int16) == v + }) + + if ok { + idx = int(e.payload.memoIdx) + found = true + } else { + idx = s.Size() + s.tbl.Insert(e, h, val.(int16), int32(idx)) + } + return +} + +// GetOrInsertBytes is unimplemented +func (s *Int16MemoTable) GetOrInsertBytes(val []byte) (idx int, found bool, err error) { + panic("unimplemented") +} + +type payloadUint16 struct { + val uint16 + memoIdx int32 +} + +type entryUint16 struct { + h uint64 + payload payloadUint16 +} + +func (e entryUint16) Valid() bool { return e.h != sentinel } + +// Uint16HashTable is a hashtable specifically for uint16 that +// is utilized with the MemoTable to generalize interactions for easier +// implementation of dictionaries without losing performance. +type Uint16HashTable struct { + cap uint64 + capMask uint64 + size uint64 + + entries []entryUint16 +} + +// NewUint16HashTable returns a new hash table for uint16 values +// initialized with the passed in capacity or 32 whichever is larger. +func NewUint16HashTable(cap uint64) *Uint16HashTable { + initCap := uint64(bitutil.NextPowerOf2(int(max(cap, 32)))) + ret := &Uint16HashTable{cap: initCap, capMask: initCap - 1, size: 0} + ret.entries = make([]entryUint16, initCap) + return ret +} + +// Reset drops all of the values in this hash table and re-initializes it +// with the specified initial capacity as if by calling New, but without having +// to reallocate the object. +func (h *Uint16HashTable) Reset(cap uint64) { + h.cap = uint64(bitutil.NextPowerOf2(int(max(cap, 32)))) + h.capMask = h.cap - 1 + h.size = 0 + h.entries = make([]entryUint16, h.cap) +} + +// CopyValues is used for copying the values out of the hash table into the +// passed in slice, in the order that they were first inserted +func (h *Uint16HashTable) CopyValues(out []uint16) { + h.CopyValuesSubset(0, out) +} + +// CopyValuesSubset copies a subset of the values in the hashtable out, starting +// with the value at start, in the order that they were inserted. +func (h *Uint16HashTable) CopyValuesSubset(start int, out []uint16) { + h.VisitEntries(func(e *entryUint16) { + idx := e.payload.memoIdx - int32(start) + if idx >= 0 { + out[idx] = e.payload.val + } + }) +} + +func (h *Uint16HashTable) WriteOut(out []byte) { + h.WriteOutSubset(0, out) +} + +func (h *Uint16HashTable) WriteOutSubset(start int, out []byte) { + data := arrow.Uint16Traits.CastFromBytes(out) + h.VisitEntries(func(e *entryUint16) { + idx := e.payload.memoIdx - int32(start) + if idx >= 0 { + data[idx] = utils.ToLEUint16(e.payload.val) + } + }) +} + +func (h *Uint16HashTable) needUpsize() bool { return h.size*uint64(loadFactor) >= h.cap } + +func (Uint16HashTable) fixHash(v uint64) uint64 { + if v == sentinel { + return 42 + } + return v +} + +// Lookup retrieves the entry for a given hash value assuming it's payload value returns +// true when passed to the cmp func. Returns a pointer to the entry for the given hash value, +// and a boolean as to whether it was found. It is not safe to use the pointer if the bool is false. +func (h *Uint16HashTable) Lookup(v uint64, cmp func(uint16) bool) (*entryUint16, bool) { + idx, ok := h.lookup(v, h.capMask, cmp) + return &h.entries[idx], ok +} + +func (h *Uint16HashTable) lookup(v uint64, szMask uint64, cmp func(uint16) bool) (uint64, bool) { + const perturbShift uint8 = 5 + + var ( + idx uint64 + perturb uint64 + e *entryUint16 + ) + + v = h.fixHash(v) + idx = v & szMask + perturb = (v >> uint64(perturbShift)) + 1 + + for { + e = &h.entries[idx] + if e.h == v && cmp(e.payload.val) { + return idx, true + } + + if e.h == sentinel { + return idx, false + } + + // perturbation logic inspired from CPython's set/dict object + // the goal is that all 64 bits of unmasked hash value eventually + // participate int he probing sequence, to minimize clustering + idx = (idx + perturb) & szMask + perturb = (perturb >> uint64(perturbShift)) + 1 + } +} + +func (h *Uint16HashTable) upsize(newcap uint64) error { + newMask := newcap - 1 + + oldEntries := h.entries + h.entries = make([]entryUint16, newcap) + for _, e := range oldEntries { + if e.Valid() { + idx, _ := h.lookup(e.h, newMask, func(uint16) bool { return false }) + h.entries[idx] = e + } + } + h.cap = newcap + h.capMask = newMask + return nil +} + +// Insert updates the given entry with the provided hash value, payload value and memo index. +// The entry pointer must have been retrieved via lookup in order to actually insert properly. +func (h *Uint16HashTable) Insert(e *entryUint16, v uint64, val uint16, memoIdx int32) error { + e.h = h.fixHash(v) + e.payload.val = val + e.payload.memoIdx = memoIdx + h.size++ + + if h.needUpsize() { + h.upsize(h.cap * uint64(loadFactor) * 2) + } + return nil +} + +// VisitEntries will call the passed in function on each *valid* entry in the hash table, +// a valid entry being one which has had a value inserted into it. +func (h *Uint16HashTable) VisitEntries(visit func(*entryUint16)) { + for _, e := range h.entries { + if e.Valid() { + visit(&e) + } + } +} + +// Uint16MemoTable is a wrapper over the appropriate hashtable to provide an interface +// conforming to the MemoTable interface defined in the encoding package for general interactions +// regarding dictionaries. +type Uint16MemoTable struct { + tbl *Uint16HashTable + nullIdx int32 +} + +// NewUint16MemoTable returns a new memotable with num entries pre-allocated to reduce further +// allocations when inserting. +func NewUint16MemoTable(num int64) *Uint16MemoTable { + return &Uint16MemoTable{tbl: NewUint16HashTable(uint64(num)), nullIdx: KeyNotFound} +} + +func (Uint16MemoTable) TypeTraits() TypeTraits { + return arrow.Uint16Traits +} + +// Reset allows this table to be re-used by dumping all the data currently in the table. +func (s *Uint16MemoTable) Reset() { + s.tbl.Reset(32) + s.nullIdx = KeyNotFound +} + +// Size returns the current number of inserted elements into the table including if a null +// has been inserted. +func (s *Uint16MemoTable) Size() int { + sz := int(s.tbl.size) + if _, ok := s.GetNull(); ok { + sz++ + } + return sz +} + +// GetNull returns the index of an inserted null or KeyNotFound along with a bool +// that will be true if found and false if not. +func (s *Uint16MemoTable) GetNull() (int, bool) { + return int(s.nullIdx), s.nullIdx != KeyNotFound +} + +// GetOrInsertNull will return the index of the null entry or insert a null entry +// if one currently doesn't exist. The found value will be true if there was already +// a null in the table, and false if it inserted one. +func (s *Uint16MemoTable) GetOrInsertNull() (idx int, found bool) { + idx, found = s.GetNull() + if !found { + idx = s.Size() + s.nullIdx = int32(idx) + } + return +} + +// CopyValues will copy the values from the memo table out into the passed in slice +// which must be of the appropriate type. +func (s *Uint16MemoTable) CopyValues(out interface{}) { + s.CopyValuesSubset(0, out) +} + +// CopyValuesSubset is like CopyValues but only copies a subset of values starting +// at the provided start index +func (s *Uint16MemoTable) CopyValuesSubset(start int, out interface{}) { + s.tbl.CopyValuesSubset(start, out.([]uint16)) +} + +func (s *Uint16MemoTable) WriteOut(out []byte) { + s.tbl.CopyValues(arrow.Uint16Traits.CastFromBytes(out)) +} + +func (s *Uint16MemoTable) WriteOutSubset(start int, out []byte) { + s.tbl.CopyValuesSubset(start, arrow.Uint16Traits.CastFromBytes(out)) +} + +func (s *Uint16MemoTable) WriteOutLE(out []byte) { + s.tbl.WriteOut(out) +} + +func (s *Uint16MemoTable) WriteOutSubsetLE(start int, out []byte) { + s.tbl.WriteOutSubset(start, out) +} + +// Get returns the index of the requested value in the hash table or KeyNotFound +// along with a boolean indicating if it was found or not. +func (s *Uint16MemoTable) Get(val interface{}) (int, bool) { + + h := hashInt(uint64(val.(uint16)), 0) + if e, ok := s.tbl.Lookup(h, func(v uint16) bool { return val.(uint16) == v }); ok { + return int(e.payload.memoIdx), ok + } + return KeyNotFound, false +} + +// GetOrInsert will return the index of the specified value in the table, or insert the +// value into the table and return the new index. found indicates whether or not it already +// existed in the table (true) or was inserted by this call (false). +func (s *Uint16MemoTable) GetOrInsert(val interface{}) (idx int, found bool, err error) { + + h := hashInt(uint64(val.(uint16)), 0) + e, ok := s.tbl.Lookup(h, func(v uint16) bool { + return val.(uint16) == v + }) + + if ok { + idx = int(e.payload.memoIdx) + found = true + } else { + idx = s.Size() + s.tbl.Insert(e, h, val.(uint16), int32(idx)) + } + return +} + +// GetOrInsertBytes is unimplemented +func (s *Uint16MemoTable) GetOrInsertBytes(val []byte) (idx int, found bool, err error) { + panic("unimplemented") +} + +type payloadInt32 struct { + val int32 + memoIdx int32 +} + +type entryInt32 struct { + h uint64 + payload payloadInt32 +} + +func (e entryInt32) Valid() bool { return e.h != sentinel } + +// Int32HashTable is a hashtable specifically for int32 that +// is utilized with the MemoTable to generalize interactions for easier +// implementation of dictionaries without losing performance. +type Int32HashTable struct { + cap uint64 + capMask uint64 + size uint64 + + entries []entryInt32 +} + +// NewInt32HashTable returns a new hash table for int32 values +// initialized with the passed in capacity or 32 whichever is larger. +func NewInt32HashTable(cap uint64) *Int32HashTable { + initCap := uint64(bitutil.NextPowerOf2(int(max(cap, 32)))) + ret := &Int32HashTable{cap: initCap, capMask: initCap - 1, size: 0} + ret.entries = make([]entryInt32, initCap) + return ret +} + +// Reset drops all of the values in this hash table and re-initializes it +// with the specified initial capacity as if by calling New, but without having +// to reallocate the object. +func (h *Int32HashTable) Reset(cap uint64) { + h.cap = uint64(bitutil.NextPowerOf2(int(max(cap, 32)))) + h.capMask = h.cap - 1 + h.size = 0 + h.entries = make([]entryInt32, h.cap) +} + +// CopyValues is used for copying the values out of the hash table into the +// passed in slice, in the order that they were first inserted +func (h *Int32HashTable) CopyValues(out []int32) { + h.CopyValuesSubset(0, out) +} + +// CopyValuesSubset copies a subset of the values in the hashtable out, starting +// with the value at start, in the order that they were inserted. +func (h *Int32HashTable) CopyValuesSubset(start int, out []int32) { + h.VisitEntries(func(e *entryInt32) { + idx := e.payload.memoIdx - int32(start) + if idx >= 0 { + out[idx] = e.payload.val + } + }) +} + +func (h *Int32HashTable) WriteOut(out []byte) { + h.WriteOutSubset(0, out) +} + +func (h *Int32HashTable) WriteOutSubset(start int, out []byte) { + data := arrow.Int32Traits.CastFromBytes(out) + h.VisitEntries(func(e *entryInt32) { + idx := e.payload.memoIdx - int32(start) + if idx >= 0 { + data[idx] = utils.ToLEInt32(e.payload.val) + } + }) +} + +func (h *Int32HashTable) needUpsize() bool { return h.size*uint64(loadFactor) >= h.cap } + +func (Int32HashTable) fixHash(v uint64) uint64 { + if v == sentinel { + return 42 + } + return v +} + +// Lookup retrieves the entry for a given hash value assuming it's payload value returns +// true when passed to the cmp func. Returns a pointer to the entry for the given hash value, +// and a boolean as to whether it was found. It is not safe to use the pointer if the bool is false. +func (h *Int32HashTable) Lookup(v uint64, cmp func(int32) bool) (*entryInt32, bool) { + idx, ok := h.lookup(v, h.capMask, cmp) + return &h.entries[idx], ok +} + +func (h *Int32HashTable) lookup(v uint64, szMask uint64, cmp func(int32) bool) (uint64, bool) { + const perturbShift uint8 = 5 + + var ( + idx uint64 + perturb uint64 + e *entryInt32 + ) + + v = h.fixHash(v) + idx = v & szMask + perturb = (v >> uint64(perturbShift)) + 1 + + for { + e = &h.entries[idx] + if e.h == v && cmp(e.payload.val) { + return idx, true + } + + if e.h == sentinel { + return idx, false + } + + // perturbation logic inspired from CPython's set/dict object + // the goal is that all 64 bits of unmasked hash value eventually + // participate int he probing sequence, to minimize clustering + idx = (idx + perturb) & szMask + perturb = (perturb >> uint64(perturbShift)) + 1 + } +} + +func (h *Int32HashTable) upsize(newcap uint64) error { + newMask := newcap - 1 + + oldEntries := h.entries + h.entries = make([]entryInt32, newcap) + for _, e := range oldEntries { + if e.Valid() { + idx, _ := h.lookup(e.h, newMask, func(int32) bool { return false }) + h.entries[idx] = e + } + } + h.cap = newcap + h.capMask = newMask + return nil +} + +// Insert updates the given entry with the provided hash value, payload value and memo index. +// The entry pointer must have been retrieved via lookup in order to actually insert properly. +func (h *Int32HashTable) Insert(e *entryInt32, v uint64, val int32, memoIdx int32) error { + e.h = h.fixHash(v) + e.payload.val = val + e.payload.memoIdx = memoIdx + h.size++ + + if h.needUpsize() { + h.upsize(h.cap * uint64(loadFactor) * 2) + } + return nil +} + +// VisitEntries will call the passed in function on each *valid* entry in the hash table, +// a valid entry being one which has had a value inserted into it. +func (h *Int32HashTable) VisitEntries(visit func(*entryInt32)) { + for _, e := range h.entries { + if e.Valid() { + visit(&e) + } + } +} + +// Int32MemoTable is a wrapper over the appropriate hashtable to provide an interface +// conforming to the MemoTable interface defined in the encoding package for general interactions +// regarding dictionaries. +type Int32MemoTable struct { + tbl *Int32HashTable + nullIdx int32 +} + +// NewInt32MemoTable returns a new memotable with num entries pre-allocated to reduce further +// allocations when inserting. +func NewInt32MemoTable(num int64) *Int32MemoTable { + return &Int32MemoTable{tbl: NewInt32HashTable(uint64(num)), nullIdx: KeyNotFound} +} + +func (Int32MemoTable) TypeTraits() TypeTraits { + return arrow.Int32Traits +} + +// Reset allows this table to be re-used by dumping all the data currently in the table. +func (s *Int32MemoTable) Reset() { + s.tbl.Reset(32) + s.nullIdx = KeyNotFound +} + +// Size returns the current number of inserted elements into the table including if a null +// has been inserted. +func (s *Int32MemoTable) Size() int { + sz := int(s.tbl.size) + if _, ok := s.GetNull(); ok { + sz++ + } + return sz +} + +// GetNull returns the index of an inserted null or KeyNotFound along with a bool +// that will be true if found and false if not. +func (s *Int32MemoTable) GetNull() (int, bool) { + return int(s.nullIdx), s.nullIdx != KeyNotFound +} + +// GetOrInsertNull will return the index of the null entry or insert a null entry +// if one currently doesn't exist. The found value will be true if there was already +// a null in the table, and false if it inserted one. +func (s *Int32MemoTable) GetOrInsertNull() (idx int, found bool) { + idx, found = s.GetNull() + if !found { + idx = s.Size() + s.nullIdx = int32(idx) + } + return +} + +// CopyValues will copy the values from the memo table out into the passed in slice +// which must be of the appropriate type. +func (s *Int32MemoTable) CopyValues(out interface{}) { + s.CopyValuesSubset(0, out) +} + +// CopyValuesSubset is like CopyValues but only copies a subset of values starting +// at the provided start index +func (s *Int32MemoTable) CopyValuesSubset(start int, out interface{}) { + s.tbl.CopyValuesSubset(start, out.([]int32)) +} + +func (s *Int32MemoTable) WriteOut(out []byte) { + s.tbl.CopyValues(arrow.Int32Traits.CastFromBytes(out)) +} + +func (s *Int32MemoTable) WriteOutSubset(start int, out []byte) { + s.tbl.CopyValuesSubset(start, arrow.Int32Traits.CastFromBytes(out)) +} + +func (s *Int32MemoTable) WriteOutLE(out []byte) { + s.tbl.WriteOut(out) +} + +func (s *Int32MemoTable) WriteOutSubsetLE(start int, out []byte) { + s.tbl.WriteOutSubset(start, out) +} + +// Get returns the index of the requested value in the hash table or KeyNotFound +// along with a boolean indicating if it was found or not. +func (s *Int32MemoTable) Get(val interface{}) (int, bool) { + + h := hashInt(uint64(val.(int32)), 0) + if e, ok := s.tbl.Lookup(h, func(v int32) bool { return val.(int32) == v }); ok { + return int(e.payload.memoIdx), ok + } + return KeyNotFound, false +} + +// GetOrInsert will return the index of the specified value in the table, or insert the +// value into the table and return the new index. found indicates whether or not it already +// existed in the table (true) or was inserted by this call (false). +func (s *Int32MemoTable) GetOrInsert(val interface{}) (idx int, found bool, err error) { + + h := hashInt(uint64(val.(int32)), 0) + e, ok := s.tbl.Lookup(h, func(v int32) bool { + return val.(int32) == v + }) + + if ok { + idx = int(e.payload.memoIdx) + found = true + } else { + idx = s.Size() + s.tbl.Insert(e, h, val.(int32), int32(idx)) + } + return +} + +// GetOrInsertBytes is unimplemented +func (s *Int32MemoTable) GetOrInsertBytes(val []byte) (idx int, found bool, err error) { + panic("unimplemented") +} + +type payloadInt64 struct { + val int64 + memoIdx int32 +} + +type entryInt64 struct { + h uint64 + payload payloadInt64 +} + +func (e entryInt64) Valid() bool { return e.h != sentinel } + +// Int64HashTable is a hashtable specifically for int64 that +// is utilized with the MemoTable to generalize interactions for easier +// implementation of dictionaries without losing performance. +type Int64HashTable struct { + cap uint64 + capMask uint64 + size uint64 + + entries []entryInt64 +} + +// NewInt64HashTable returns a new hash table for int64 values +// initialized with the passed in capacity or 32 whichever is larger. +func NewInt64HashTable(cap uint64) *Int64HashTable { + initCap := uint64(bitutil.NextPowerOf2(int(max(cap, 32)))) + ret := &Int64HashTable{cap: initCap, capMask: initCap - 1, size: 0} + ret.entries = make([]entryInt64, initCap) + return ret +} + +// Reset drops all of the values in this hash table and re-initializes it +// with the specified initial capacity as if by calling New, but without having +// to reallocate the object. +func (h *Int64HashTable) Reset(cap uint64) { + h.cap = uint64(bitutil.NextPowerOf2(int(max(cap, 32)))) + h.capMask = h.cap - 1 + h.size = 0 + h.entries = make([]entryInt64, h.cap) +} + +// CopyValues is used for copying the values out of the hash table into the +// passed in slice, in the order that they were first inserted +func (h *Int64HashTable) CopyValues(out []int64) { + h.CopyValuesSubset(0, out) +} + +// CopyValuesSubset copies a subset of the values in the hashtable out, starting +// with the value at start, in the order that they were inserted. +func (h *Int64HashTable) CopyValuesSubset(start int, out []int64) { + h.VisitEntries(func(e *entryInt64) { + idx := e.payload.memoIdx - int32(start) + if idx >= 0 { + out[idx] = e.payload.val + } + }) +} + +func (h *Int64HashTable) WriteOut(out []byte) { + h.WriteOutSubset(0, out) +} + +func (h *Int64HashTable) WriteOutSubset(start int, out []byte) { + data := arrow.Int64Traits.CastFromBytes(out) + h.VisitEntries(func(e *entryInt64) { + idx := e.payload.memoIdx - int32(start) + if idx >= 0 { + data[idx] = utils.ToLEInt64(e.payload.val) + } + }) +} + +func (h *Int64HashTable) needUpsize() bool { return h.size*uint64(loadFactor) >= h.cap } + +func (Int64HashTable) fixHash(v uint64) uint64 { + if v == sentinel { + return 42 + } + return v +} + +// Lookup retrieves the entry for a given hash value assuming it's payload value returns +// true when passed to the cmp func. Returns a pointer to the entry for the given hash value, +// and a boolean as to whether it was found. It is not safe to use the pointer if the bool is false. +func (h *Int64HashTable) Lookup(v uint64, cmp func(int64) bool) (*entryInt64, bool) { + idx, ok := h.lookup(v, h.capMask, cmp) + return &h.entries[idx], ok +} + +func (h *Int64HashTable) lookup(v uint64, szMask uint64, cmp func(int64) bool) (uint64, bool) { + const perturbShift uint8 = 5 + + var ( + idx uint64 + perturb uint64 + e *entryInt64 + ) + + v = h.fixHash(v) + idx = v & szMask + perturb = (v >> uint64(perturbShift)) + 1 + + for { + e = &h.entries[idx] + if e.h == v && cmp(e.payload.val) { + return idx, true + } + + if e.h == sentinel { + return idx, false + } + + // perturbation logic inspired from CPython's set/dict object + // the goal is that all 64 bits of unmasked hash value eventually + // participate int he probing sequence, to minimize clustering + idx = (idx + perturb) & szMask + perturb = (perturb >> uint64(perturbShift)) + 1 + } +} + +func (h *Int64HashTable) upsize(newcap uint64) error { + newMask := newcap - 1 + + oldEntries := h.entries + h.entries = make([]entryInt64, newcap) + for _, e := range oldEntries { + if e.Valid() { + idx, _ := h.lookup(e.h, newMask, func(int64) bool { return false }) + h.entries[idx] = e + } + } + h.cap = newcap + h.capMask = newMask + return nil +} + +// Insert updates the given entry with the provided hash value, payload value and memo index. +// The entry pointer must have been retrieved via lookup in order to actually insert properly. +func (h *Int64HashTable) Insert(e *entryInt64, v uint64, val int64, memoIdx int32) error { + e.h = h.fixHash(v) + e.payload.val = val + e.payload.memoIdx = memoIdx + h.size++ + + if h.needUpsize() { + h.upsize(h.cap * uint64(loadFactor) * 2) + } + return nil +} + +// VisitEntries will call the passed in function on each *valid* entry in the hash table, +// a valid entry being one which has had a value inserted into it. +func (h *Int64HashTable) VisitEntries(visit func(*entryInt64)) { + for _, e := range h.entries { + if e.Valid() { + visit(&e) + } + } +} + +// Int64MemoTable is a wrapper over the appropriate hashtable to provide an interface +// conforming to the MemoTable interface defined in the encoding package for general interactions +// regarding dictionaries. +type Int64MemoTable struct { + tbl *Int64HashTable + nullIdx int32 +} + +// NewInt64MemoTable returns a new memotable with num entries pre-allocated to reduce further +// allocations when inserting. +func NewInt64MemoTable(num int64) *Int64MemoTable { + return &Int64MemoTable{tbl: NewInt64HashTable(uint64(num)), nullIdx: KeyNotFound} +} + +func (Int64MemoTable) TypeTraits() TypeTraits { + return arrow.Int64Traits +} + +// Reset allows this table to be re-used by dumping all the data currently in the table. +func (s *Int64MemoTable) Reset() { + s.tbl.Reset(32) + s.nullIdx = KeyNotFound +} + +// Size returns the current number of inserted elements into the table including if a null +// has been inserted. +func (s *Int64MemoTable) Size() int { + sz := int(s.tbl.size) + if _, ok := s.GetNull(); ok { + sz++ + } + return sz +} + +// GetNull returns the index of an inserted null or KeyNotFound along with a bool +// that will be true if found and false if not. +func (s *Int64MemoTable) GetNull() (int, bool) { + return int(s.nullIdx), s.nullIdx != KeyNotFound +} + +// GetOrInsertNull will return the index of the null entry or insert a null entry +// if one currently doesn't exist. The found value will be true if there was already +// a null in the table, and false if it inserted one. +func (s *Int64MemoTable) GetOrInsertNull() (idx int, found bool) { + idx, found = s.GetNull() + if !found { + idx = s.Size() + s.nullIdx = int32(idx) + } + return +} + +// CopyValues will copy the values from the memo table out into the passed in slice +// which must be of the appropriate type. +func (s *Int64MemoTable) CopyValues(out interface{}) { + s.CopyValuesSubset(0, out) +} + +// CopyValuesSubset is like CopyValues but only copies a subset of values starting +// at the provided start index +func (s *Int64MemoTable) CopyValuesSubset(start int, out interface{}) { + s.tbl.CopyValuesSubset(start, out.([]int64)) +} + +func (s *Int64MemoTable) WriteOut(out []byte) { + s.tbl.CopyValues(arrow.Int64Traits.CastFromBytes(out)) +} + +func (s *Int64MemoTable) WriteOutSubset(start int, out []byte) { + s.tbl.CopyValuesSubset(start, arrow.Int64Traits.CastFromBytes(out)) +} + +func (s *Int64MemoTable) WriteOutLE(out []byte) { + s.tbl.WriteOut(out) +} + +func (s *Int64MemoTable) WriteOutSubsetLE(start int, out []byte) { + s.tbl.WriteOutSubset(start, out) +} + +// Get returns the index of the requested value in the hash table or KeyNotFound +// along with a boolean indicating if it was found or not. +func (s *Int64MemoTable) Get(val interface{}) (int, bool) { + + h := hashInt(uint64(val.(int64)), 0) + if e, ok := s.tbl.Lookup(h, func(v int64) bool { return val.(int64) == v }); ok { + return int(e.payload.memoIdx), ok + } + return KeyNotFound, false +} + +// GetOrInsert will return the index of the specified value in the table, or insert the +// value into the table and return the new index. found indicates whether or not it already +// existed in the table (true) or was inserted by this call (false). +func (s *Int64MemoTable) GetOrInsert(val interface{}) (idx int, found bool, err error) { + + h := hashInt(uint64(val.(int64)), 0) + e, ok := s.tbl.Lookup(h, func(v int64) bool { + return val.(int64) == v + }) + + if ok { + idx = int(e.payload.memoIdx) + found = true + } else { + idx = s.Size() + s.tbl.Insert(e, h, val.(int64), int32(idx)) + } + return +} + +// GetOrInsertBytes is unimplemented +func (s *Int64MemoTable) GetOrInsertBytes(val []byte) (idx int, found bool, err error) { + panic("unimplemented") +} + +type payloadUint32 struct { + val uint32 + memoIdx int32 +} + +type entryUint32 struct { + h uint64 + payload payloadUint32 +} + +func (e entryUint32) Valid() bool { return e.h != sentinel } + +// Uint32HashTable is a hashtable specifically for uint32 that +// is utilized with the MemoTable to generalize interactions for easier +// implementation of dictionaries without losing performance. +type Uint32HashTable struct { + cap uint64 + capMask uint64 + size uint64 + + entries []entryUint32 +} + +// NewUint32HashTable returns a new hash table for uint32 values +// initialized with the passed in capacity or 32 whichever is larger. +func NewUint32HashTable(cap uint64) *Uint32HashTable { + initCap := uint64(bitutil.NextPowerOf2(int(max(cap, 32)))) + ret := &Uint32HashTable{cap: initCap, capMask: initCap - 1, size: 0} + ret.entries = make([]entryUint32, initCap) + return ret +} + +// Reset drops all of the values in this hash table and re-initializes it +// with the specified initial capacity as if by calling New, but without having +// to reallocate the object. +func (h *Uint32HashTable) Reset(cap uint64) { + h.cap = uint64(bitutil.NextPowerOf2(int(max(cap, 32)))) + h.capMask = h.cap - 1 + h.size = 0 + h.entries = make([]entryUint32, h.cap) +} + +// CopyValues is used for copying the values out of the hash table into the +// passed in slice, in the order that they were first inserted +func (h *Uint32HashTable) CopyValues(out []uint32) { + h.CopyValuesSubset(0, out) +} + +// CopyValuesSubset copies a subset of the values in the hashtable out, starting +// with the value at start, in the order that they were inserted. +func (h *Uint32HashTable) CopyValuesSubset(start int, out []uint32) { + h.VisitEntries(func(e *entryUint32) { + idx := e.payload.memoIdx - int32(start) + if idx >= 0 { + out[idx] = e.payload.val + } + }) +} + +func (h *Uint32HashTable) WriteOut(out []byte) { + h.WriteOutSubset(0, out) +} + +func (h *Uint32HashTable) WriteOutSubset(start int, out []byte) { + data := arrow.Uint32Traits.CastFromBytes(out) + h.VisitEntries(func(e *entryUint32) { + idx := e.payload.memoIdx - int32(start) + if idx >= 0 { + data[idx] = utils.ToLEUint32(e.payload.val) + } + }) +} + +func (h *Uint32HashTable) needUpsize() bool { return h.size*uint64(loadFactor) >= h.cap } + +func (Uint32HashTable) fixHash(v uint64) uint64 { + if v == sentinel { + return 42 + } + return v +} + +// Lookup retrieves the entry for a given hash value assuming it's payload value returns +// true when passed to the cmp func. Returns a pointer to the entry for the given hash value, +// and a boolean as to whether it was found. It is not safe to use the pointer if the bool is false. +func (h *Uint32HashTable) Lookup(v uint64, cmp func(uint32) bool) (*entryUint32, bool) { + idx, ok := h.lookup(v, h.capMask, cmp) + return &h.entries[idx], ok +} + +func (h *Uint32HashTable) lookup(v uint64, szMask uint64, cmp func(uint32) bool) (uint64, bool) { + const perturbShift uint8 = 5 + + var ( + idx uint64 + perturb uint64 + e *entryUint32 + ) + + v = h.fixHash(v) + idx = v & szMask + perturb = (v >> uint64(perturbShift)) + 1 + + for { + e = &h.entries[idx] + if e.h == v && cmp(e.payload.val) { + return idx, true + } + + if e.h == sentinel { + return idx, false + } + + // perturbation logic inspired from CPython's set/dict object + // the goal is that all 64 bits of unmasked hash value eventually + // participate int he probing sequence, to minimize clustering + idx = (idx + perturb) & szMask + perturb = (perturb >> uint64(perturbShift)) + 1 + } +} + +func (h *Uint32HashTable) upsize(newcap uint64) error { + newMask := newcap - 1 + + oldEntries := h.entries + h.entries = make([]entryUint32, newcap) + for _, e := range oldEntries { + if e.Valid() { + idx, _ := h.lookup(e.h, newMask, func(uint32) bool { return false }) + h.entries[idx] = e + } + } + h.cap = newcap + h.capMask = newMask + return nil +} + +// Insert updates the given entry with the provided hash value, payload value and memo index. +// The entry pointer must have been retrieved via lookup in order to actually insert properly. +func (h *Uint32HashTable) Insert(e *entryUint32, v uint64, val uint32, memoIdx int32) error { + e.h = h.fixHash(v) + e.payload.val = val + e.payload.memoIdx = memoIdx + h.size++ + + if h.needUpsize() { + h.upsize(h.cap * uint64(loadFactor) * 2) + } + return nil +} + +// VisitEntries will call the passed in function on each *valid* entry in the hash table, +// a valid entry being one which has had a value inserted into it. +func (h *Uint32HashTable) VisitEntries(visit func(*entryUint32)) { + for _, e := range h.entries { + if e.Valid() { + visit(&e) + } + } +} + +// Uint32MemoTable is a wrapper over the appropriate hashtable to provide an interface +// conforming to the MemoTable interface defined in the encoding package for general interactions +// regarding dictionaries. +type Uint32MemoTable struct { + tbl *Uint32HashTable + nullIdx int32 +} + +// NewUint32MemoTable returns a new memotable with num entries pre-allocated to reduce further +// allocations when inserting. +func NewUint32MemoTable(num int64) *Uint32MemoTable { + return &Uint32MemoTable{tbl: NewUint32HashTable(uint64(num)), nullIdx: KeyNotFound} +} + +func (Uint32MemoTable) TypeTraits() TypeTraits { + return arrow.Uint32Traits +} + +// Reset allows this table to be re-used by dumping all the data currently in the table. +func (s *Uint32MemoTable) Reset() { + s.tbl.Reset(32) + s.nullIdx = KeyNotFound +} + +// Size returns the current number of inserted elements into the table including if a null +// has been inserted. +func (s *Uint32MemoTable) Size() int { + sz := int(s.tbl.size) + if _, ok := s.GetNull(); ok { + sz++ + } + return sz +} + +// GetNull returns the index of an inserted null or KeyNotFound along with a bool +// that will be true if found and false if not. +func (s *Uint32MemoTable) GetNull() (int, bool) { + return int(s.nullIdx), s.nullIdx != KeyNotFound +} + +// GetOrInsertNull will return the index of the null entry or insert a null entry +// if one currently doesn't exist. The found value will be true if there was already +// a null in the table, and false if it inserted one. +func (s *Uint32MemoTable) GetOrInsertNull() (idx int, found bool) { + idx, found = s.GetNull() + if !found { + idx = s.Size() + s.nullIdx = int32(idx) + } + return +} + +// CopyValues will copy the values from the memo table out into the passed in slice +// which must be of the appropriate type. +func (s *Uint32MemoTable) CopyValues(out interface{}) { + s.CopyValuesSubset(0, out) +} + +// CopyValuesSubset is like CopyValues but only copies a subset of values starting +// at the provided start index +func (s *Uint32MemoTable) CopyValuesSubset(start int, out interface{}) { + s.tbl.CopyValuesSubset(start, out.([]uint32)) +} + +func (s *Uint32MemoTable) WriteOut(out []byte) { + s.tbl.CopyValues(arrow.Uint32Traits.CastFromBytes(out)) +} + +func (s *Uint32MemoTable) WriteOutSubset(start int, out []byte) { + s.tbl.CopyValuesSubset(start, arrow.Uint32Traits.CastFromBytes(out)) +} + +func (s *Uint32MemoTable) WriteOutLE(out []byte) { + s.tbl.WriteOut(out) +} + +func (s *Uint32MemoTable) WriteOutSubsetLE(start int, out []byte) { + s.tbl.WriteOutSubset(start, out) +} + +// Get returns the index of the requested value in the hash table or KeyNotFound +// along with a boolean indicating if it was found or not. +func (s *Uint32MemoTable) Get(val interface{}) (int, bool) { + + h := hashInt(uint64(val.(uint32)), 0) + if e, ok := s.tbl.Lookup(h, func(v uint32) bool { return val.(uint32) == v }); ok { + return int(e.payload.memoIdx), ok + } + return KeyNotFound, false +} + +// GetOrInsert will return the index of the specified value in the table, or insert the +// value into the table and return the new index. found indicates whether or not it already +// existed in the table (true) or was inserted by this call (false). +func (s *Uint32MemoTable) GetOrInsert(val interface{}) (idx int, found bool, err error) { + + h := hashInt(uint64(val.(uint32)), 0) + e, ok := s.tbl.Lookup(h, func(v uint32) bool { + return val.(uint32) == v + }) + + if ok { + idx = int(e.payload.memoIdx) + found = true + } else { + idx = s.Size() + s.tbl.Insert(e, h, val.(uint32), int32(idx)) + } + return +} + +// GetOrInsertBytes is unimplemented +func (s *Uint32MemoTable) GetOrInsertBytes(val []byte) (idx int, found bool, err error) { + panic("unimplemented") +} + +type payloadUint64 struct { + val uint64 + memoIdx int32 +} + +type entryUint64 struct { + h uint64 + payload payloadUint64 +} + +func (e entryUint64) Valid() bool { return e.h != sentinel } + +// Uint64HashTable is a hashtable specifically for uint64 that +// is utilized with the MemoTable to generalize interactions for easier +// implementation of dictionaries without losing performance. +type Uint64HashTable struct { + cap uint64 + capMask uint64 + size uint64 + + entries []entryUint64 +} + +// NewUint64HashTable returns a new hash table for uint64 values +// initialized with the passed in capacity or 32 whichever is larger. +func NewUint64HashTable(cap uint64) *Uint64HashTable { + initCap := uint64(bitutil.NextPowerOf2(int(max(cap, 32)))) + ret := &Uint64HashTable{cap: initCap, capMask: initCap - 1, size: 0} + ret.entries = make([]entryUint64, initCap) + return ret +} + +// Reset drops all of the values in this hash table and re-initializes it +// with the specified initial capacity as if by calling New, but without having +// to reallocate the object. +func (h *Uint64HashTable) Reset(cap uint64) { + h.cap = uint64(bitutil.NextPowerOf2(int(max(cap, 32)))) + h.capMask = h.cap - 1 + h.size = 0 + h.entries = make([]entryUint64, h.cap) +} + +// CopyValues is used for copying the values out of the hash table into the +// passed in slice, in the order that they were first inserted +func (h *Uint64HashTable) CopyValues(out []uint64) { + h.CopyValuesSubset(0, out) +} + +// CopyValuesSubset copies a subset of the values in the hashtable out, starting +// with the value at start, in the order that they were inserted. +func (h *Uint64HashTable) CopyValuesSubset(start int, out []uint64) { + h.VisitEntries(func(e *entryUint64) { + idx := e.payload.memoIdx - int32(start) + if idx >= 0 { + out[idx] = e.payload.val + } + }) +} + +func (h *Uint64HashTable) WriteOut(out []byte) { + h.WriteOutSubset(0, out) +} + +func (h *Uint64HashTable) WriteOutSubset(start int, out []byte) { + data := arrow.Uint64Traits.CastFromBytes(out) + h.VisitEntries(func(e *entryUint64) { + idx := e.payload.memoIdx - int32(start) + if idx >= 0 { + data[idx] = utils.ToLEUint64(e.payload.val) + } + }) +} + +func (h *Uint64HashTable) needUpsize() bool { return h.size*uint64(loadFactor) >= h.cap } + +func (Uint64HashTable) fixHash(v uint64) uint64 { + if v == sentinel { + return 42 + } + return v +} + +// Lookup retrieves the entry for a given hash value assuming it's payload value returns +// true when passed to the cmp func. Returns a pointer to the entry for the given hash value, +// and a boolean as to whether it was found. It is not safe to use the pointer if the bool is false. +func (h *Uint64HashTable) Lookup(v uint64, cmp func(uint64) bool) (*entryUint64, bool) { + idx, ok := h.lookup(v, h.capMask, cmp) + return &h.entries[idx], ok +} + +func (h *Uint64HashTable) lookup(v uint64, szMask uint64, cmp func(uint64) bool) (uint64, bool) { + const perturbShift uint8 = 5 + + var ( + idx uint64 + perturb uint64 + e *entryUint64 + ) + + v = h.fixHash(v) + idx = v & szMask + perturb = (v >> uint64(perturbShift)) + 1 + + for { + e = &h.entries[idx] + if e.h == v && cmp(e.payload.val) { + return idx, true + } + + if e.h == sentinel { + return idx, false + } + + // perturbation logic inspired from CPython's set/dict object + // the goal is that all 64 bits of unmasked hash value eventually + // participate int he probing sequence, to minimize clustering + idx = (idx + perturb) & szMask + perturb = (perturb >> uint64(perturbShift)) + 1 + } +} + +func (h *Uint64HashTable) upsize(newcap uint64) error { + newMask := newcap - 1 + + oldEntries := h.entries + h.entries = make([]entryUint64, newcap) + for _, e := range oldEntries { + if e.Valid() { + idx, _ := h.lookup(e.h, newMask, func(uint64) bool { return false }) + h.entries[idx] = e + } + } + h.cap = newcap + h.capMask = newMask + return nil +} + +// Insert updates the given entry with the provided hash value, payload value and memo index. +// The entry pointer must have been retrieved via lookup in order to actually insert properly. +func (h *Uint64HashTable) Insert(e *entryUint64, v uint64, val uint64, memoIdx int32) error { + e.h = h.fixHash(v) + e.payload.val = val + e.payload.memoIdx = memoIdx + h.size++ + + if h.needUpsize() { + h.upsize(h.cap * uint64(loadFactor) * 2) + } + return nil +} + +// VisitEntries will call the passed in function on each *valid* entry in the hash table, +// a valid entry being one which has had a value inserted into it. +func (h *Uint64HashTable) VisitEntries(visit func(*entryUint64)) { + for _, e := range h.entries { + if e.Valid() { + visit(&e) + } + } +} + +// Uint64MemoTable is a wrapper over the appropriate hashtable to provide an interface +// conforming to the MemoTable interface defined in the encoding package for general interactions +// regarding dictionaries. +type Uint64MemoTable struct { + tbl *Uint64HashTable + nullIdx int32 +} + +// NewUint64MemoTable returns a new memotable with num entries pre-allocated to reduce further +// allocations when inserting. +func NewUint64MemoTable(num int64) *Uint64MemoTable { + return &Uint64MemoTable{tbl: NewUint64HashTable(uint64(num)), nullIdx: KeyNotFound} +} + +func (Uint64MemoTable) TypeTraits() TypeTraits { + return arrow.Uint64Traits +} + +// Reset allows this table to be re-used by dumping all the data currently in the table. +func (s *Uint64MemoTable) Reset() { + s.tbl.Reset(32) + s.nullIdx = KeyNotFound +} + +// Size returns the current number of inserted elements into the table including if a null +// has been inserted. +func (s *Uint64MemoTable) Size() int { + sz := int(s.tbl.size) + if _, ok := s.GetNull(); ok { + sz++ + } + return sz +} + +// GetNull returns the index of an inserted null or KeyNotFound along with a bool +// that will be true if found and false if not. +func (s *Uint64MemoTable) GetNull() (int, bool) { + return int(s.nullIdx), s.nullIdx != KeyNotFound +} + +// GetOrInsertNull will return the index of the null entry or insert a null entry +// if one currently doesn't exist. The found value will be true if there was already +// a null in the table, and false if it inserted one. +func (s *Uint64MemoTable) GetOrInsertNull() (idx int, found bool) { + idx, found = s.GetNull() + if !found { + idx = s.Size() + s.nullIdx = int32(idx) + } + return +} + +// CopyValues will copy the values from the memo table out into the passed in slice +// which must be of the appropriate type. +func (s *Uint64MemoTable) CopyValues(out interface{}) { + s.CopyValuesSubset(0, out) +} + +// CopyValuesSubset is like CopyValues but only copies a subset of values starting +// at the provided start index +func (s *Uint64MemoTable) CopyValuesSubset(start int, out interface{}) { + s.tbl.CopyValuesSubset(start, out.([]uint64)) +} + +func (s *Uint64MemoTable) WriteOut(out []byte) { + s.tbl.CopyValues(arrow.Uint64Traits.CastFromBytes(out)) +} + +func (s *Uint64MemoTable) WriteOutSubset(start int, out []byte) { + s.tbl.CopyValuesSubset(start, arrow.Uint64Traits.CastFromBytes(out)) +} + +func (s *Uint64MemoTable) WriteOutLE(out []byte) { + s.tbl.WriteOut(out) +} + +func (s *Uint64MemoTable) WriteOutSubsetLE(start int, out []byte) { + s.tbl.WriteOutSubset(start, out) +} + +// Get returns the index of the requested value in the hash table or KeyNotFound +// along with a boolean indicating if it was found or not. +func (s *Uint64MemoTable) Get(val interface{}) (int, bool) { + + h := hashInt(uint64(val.(uint64)), 0) + if e, ok := s.tbl.Lookup(h, func(v uint64) bool { return val.(uint64) == v }); ok { + return int(e.payload.memoIdx), ok + } + return KeyNotFound, false +} + +// GetOrInsert will return the index of the specified value in the table, or insert the +// value into the table and return the new index. found indicates whether or not it already +// existed in the table (true) or was inserted by this call (false). +func (s *Uint64MemoTable) GetOrInsert(val interface{}) (idx int, found bool, err error) { + + h := hashInt(uint64(val.(uint64)), 0) + e, ok := s.tbl.Lookup(h, func(v uint64) bool { + return val.(uint64) == v + }) + + if ok { + idx = int(e.payload.memoIdx) + found = true + } else { + idx = s.Size() + s.tbl.Insert(e, h, val.(uint64), int32(idx)) + } + return +} + +// GetOrInsertBytes is unimplemented +func (s *Uint64MemoTable) GetOrInsertBytes(val []byte) (idx int, found bool, err error) { + panic("unimplemented") +} + +type payloadFloat32 struct { + val float32 + memoIdx int32 +} + +type entryFloat32 struct { + h uint64 + payload payloadFloat32 +} + +func (e entryFloat32) Valid() bool { return e.h != sentinel } + +// Float32HashTable is a hashtable specifically for float32 that +// is utilized with the MemoTable to generalize interactions for easier +// implementation of dictionaries without losing performance. +type Float32HashTable struct { + cap uint64 + capMask uint64 + size uint64 + + entries []entryFloat32 +} + +// NewFloat32HashTable returns a new hash table for float32 values +// initialized with the passed in capacity or 32 whichever is larger. +func NewFloat32HashTable(cap uint64) *Float32HashTable { + initCap := uint64(bitutil.NextPowerOf2(int(max(cap, 32)))) + ret := &Float32HashTable{cap: initCap, capMask: initCap - 1, size: 0} + ret.entries = make([]entryFloat32, initCap) + return ret +} + +// Reset drops all of the values in this hash table and re-initializes it +// with the specified initial capacity as if by calling New, but without having +// to reallocate the object. +func (h *Float32HashTable) Reset(cap uint64) { + h.cap = uint64(bitutil.NextPowerOf2(int(max(cap, 32)))) + h.capMask = h.cap - 1 + h.size = 0 + h.entries = make([]entryFloat32, h.cap) +} + +// CopyValues is used for copying the values out of the hash table into the +// passed in slice, in the order that they were first inserted +func (h *Float32HashTable) CopyValues(out []float32) { + h.CopyValuesSubset(0, out) +} + +// CopyValuesSubset copies a subset of the values in the hashtable out, starting +// with the value at start, in the order that they were inserted. +func (h *Float32HashTable) CopyValuesSubset(start int, out []float32) { + h.VisitEntries(func(e *entryFloat32) { + idx := e.payload.memoIdx - int32(start) + if idx >= 0 { + out[idx] = e.payload.val + } + }) +} + +func (h *Float32HashTable) WriteOut(out []byte) { + h.WriteOutSubset(0, out) +} + +func (h *Float32HashTable) WriteOutSubset(start int, out []byte) { + data := arrow.Float32Traits.CastFromBytes(out) + h.VisitEntries(func(e *entryFloat32) { + idx := e.payload.memoIdx - int32(start) + if idx >= 0 { + data[idx] = utils.ToLEFloat32(e.payload.val) + } + }) +} + +func (h *Float32HashTable) needUpsize() bool { return h.size*uint64(loadFactor) >= h.cap } + +func (Float32HashTable) fixHash(v uint64) uint64 { + if v == sentinel { + return 42 + } + return v +} + +// Lookup retrieves the entry for a given hash value assuming it's payload value returns +// true when passed to the cmp func. Returns a pointer to the entry for the given hash value, +// and a boolean as to whether it was found. It is not safe to use the pointer if the bool is false. +func (h *Float32HashTable) Lookup(v uint64, cmp func(float32) bool) (*entryFloat32, bool) { + idx, ok := h.lookup(v, h.capMask, cmp) + return &h.entries[idx], ok +} + +func (h *Float32HashTable) lookup(v uint64, szMask uint64, cmp func(float32) bool) (uint64, bool) { + const perturbShift uint8 = 5 + + var ( + idx uint64 + perturb uint64 + e *entryFloat32 + ) + + v = h.fixHash(v) + idx = v & szMask + perturb = (v >> uint64(perturbShift)) + 1 + + for { + e = &h.entries[idx] + if e.h == v && cmp(e.payload.val) { + return idx, true + } + + if e.h == sentinel { + return idx, false + } + + // perturbation logic inspired from CPython's set/dict object + // the goal is that all 64 bits of unmasked hash value eventually + // participate int he probing sequence, to minimize clustering + idx = (idx + perturb) & szMask + perturb = (perturb >> uint64(perturbShift)) + 1 + } +} + +func (h *Float32HashTable) upsize(newcap uint64) error { + newMask := newcap - 1 + + oldEntries := h.entries + h.entries = make([]entryFloat32, newcap) + for _, e := range oldEntries { + if e.Valid() { + idx, _ := h.lookup(e.h, newMask, func(float32) bool { return false }) + h.entries[idx] = e + } + } + h.cap = newcap + h.capMask = newMask + return nil +} + +// Insert updates the given entry with the provided hash value, payload value and memo index. +// The entry pointer must have been retrieved via lookup in order to actually insert properly. +func (h *Float32HashTable) Insert(e *entryFloat32, v uint64, val float32, memoIdx int32) error { + e.h = h.fixHash(v) + e.payload.val = val + e.payload.memoIdx = memoIdx + h.size++ + + if h.needUpsize() { + h.upsize(h.cap * uint64(loadFactor) * 2) + } + return nil +} + +// VisitEntries will call the passed in function on each *valid* entry in the hash table, +// a valid entry being one which has had a value inserted into it. +func (h *Float32HashTable) VisitEntries(visit func(*entryFloat32)) { + for _, e := range h.entries { + if e.Valid() { + visit(&e) + } + } +} + +// Float32MemoTable is a wrapper over the appropriate hashtable to provide an interface +// conforming to the MemoTable interface defined in the encoding package for general interactions +// regarding dictionaries. +type Float32MemoTable struct { + tbl *Float32HashTable + nullIdx int32 +} + +// NewFloat32MemoTable returns a new memotable with num entries pre-allocated to reduce further +// allocations when inserting. +func NewFloat32MemoTable(num int64) *Float32MemoTable { + return &Float32MemoTable{tbl: NewFloat32HashTable(uint64(num)), nullIdx: KeyNotFound} +} + +func (Float32MemoTable) TypeTraits() TypeTraits { + return arrow.Float32Traits +} + +// Reset allows this table to be re-used by dumping all the data currently in the table. +func (s *Float32MemoTable) Reset() { + s.tbl.Reset(32) + s.nullIdx = KeyNotFound +} + +// Size returns the current number of inserted elements into the table including if a null +// has been inserted. +func (s *Float32MemoTable) Size() int { + sz := int(s.tbl.size) + if _, ok := s.GetNull(); ok { + sz++ + } + return sz +} + +// GetNull returns the index of an inserted null or KeyNotFound along with a bool +// that will be true if found and false if not. +func (s *Float32MemoTable) GetNull() (int, bool) { + return int(s.nullIdx), s.nullIdx != KeyNotFound +} + +// GetOrInsertNull will return the index of the null entry or insert a null entry +// if one currently doesn't exist. The found value will be true if there was already +// a null in the table, and false if it inserted one. +func (s *Float32MemoTable) GetOrInsertNull() (idx int, found bool) { + idx, found = s.GetNull() + if !found { + idx = s.Size() + s.nullIdx = int32(idx) + } + return +} + +// CopyValues will copy the values from the memo table out into the passed in slice +// which must be of the appropriate type. +func (s *Float32MemoTable) CopyValues(out interface{}) { + s.CopyValuesSubset(0, out) +} + +// CopyValuesSubset is like CopyValues but only copies a subset of values starting +// at the provided start index +func (s *Float32MemoTable) CopyValuesSubset(start int, out interface{}) { + s.tbl.CopyValuesSubset(start, out.([]float32)) +} + +func (s *Float32MemoTable) WriteOut(out []byte) { + s.tbl.CopyValues(arrow.Float32Traits.CastFromBytes(out)) +} + +func (s *Float32MemoTable) WriteOutSubset(start int, out []byte) { + s.tbl.CopyValuesSubset(start, arrow.Float32Traits.CastFromBytes(out)) +} + +func (s *Float32MemoTable) WriteOutLE(out []byte) { + s.tbl.WriteOut(out) +} + +func (s *Float32MemoTable) WriteOutSubsetLE(start int, out []byte) { + s.tbl.WriteOutSubset(start, out) +} + +// Get returns the index of the requested value in the hash table or KeyNotFound +// along with a boolean indicating if it was found or not. +func (s *Float32MemoTable) Get(val interface{}) (int, bool) { + var cmp func(float32) bool + + if math.IsNaN(float64(val.(float32))) { + cmp = isNan32Cmp + // use consistent internal bit pattern for NaN regardless of the pattern + // that is passed to us. NaN is NaN is NaN + val = float32(math.NaN()) + } else { + cmp = func(v float32) bool { return val.(float32) == v } + } + + h := hashFloat32(val.(float32), 0) + if e, ok := s.tbl.Lookup(h, cmp); ok { + return int(e.payload.memoIdx), ok + } + return KeyNotFound, false +} + +// GetOrInsert will return the index of the specified value in the table, or insert the +// value into the table and return the new index. found indicates whether or not it already +// existed in the table (true) or was inserted by this call (false). +func (s *Float32MemoTable) GetOrInsert(val interface{}) (idx int, found bool, err error) { + + var cmp func(float32) bool + + if math.IsNaN(float64(val.(float32))) { + cmp = isNan32Cmp + // use consistent internal bit pattern for NaN regardless of the pattern + // that is passed to us. NaN is NaN is NaN + val = float32(math.NaN()) + } else { + cmp = func(v float32) bool { return val.(float32) == v } + } + + h := hashFloat32(val.(float32), 0) + e, ok := s.tbl.Lookup(h, cmp) + + if ok { + idx = int(e.payload.memoIdx) + found = true + } else { + idx = s.Size() + s.tbl.Insert(e, h, val.(float32), int32(idx)) + } + return +} + +// GetOrInsertBytes is unimplemented +func (s *Float32MemoTable) GetOrInsertBytes(val []byte) (idx int, found bool, err error) { + panic("unimplemented") +} + +type payloadFloat64 struct { + val float64 + memoIdx int32 +} + +type entryFloat64 struct { + h uint64 + payload payloadFloat64 +} + +func (e entryFloat64) Valid() bool { return e.h != sentinel } + +// Float64HashTable is a hashtable specifically for float64 that +// is utilized with the MemoTable to generalize interactions for easier +// implementation of dictionaries without losing performance. +type Float64HashTable struct { + cap uint64 + capMask uint64 + size uint64 + + entries []entryFloat64 +} + +// NewFloat64HashTable returns a new hash table for float64 values +// initialized with the passed in capacity or 32 whichever is larger. +func NewFloat64HashTable(cap uint64) *Float64HashTable { + initCap := uint64(bitutil.NextPowerOf2(int(max(cap, 32)))) + ret := &Float64HashTable{cap: initCap, capMask: initCap - 1, size: 0} + ret.entries = make([]entryFloat64, initCap) + return ret +} + +// Reset drops all of the values in this hash table and re-initializes it +// with the specified initial capacity as if by calling New, but without having +// to reallocate the object. +func (h *Float64HashTable) Reset(cap uint64) { + h.cap = uint64(bitutil.NextPowerOf2(int(max(cap, 32)))) + h.capMask = h.cap - 1 + h.size = 0 + h.entries = make([]entryFloat64, h.cap) +} + +// CopyValues is used for copying the values out of the hash table into the +// passed in slice, in the order that they were first inserted +func (h *Float64HashTable) CopyValues(out []float64) { + h.CopyValuesSubset(0, out) +} + +// CopyValuesSubset copies a subset of the values in the hashtable out, starting +// with the value at start, in the order that they were inserted. +func (h *Float64HashTable) CopyValuesSubset(start int, out []float64) { + h.VisitEntries(func(e *entryFloat64) { + idx := e.payload.memoIdx - int32(start) + if idx >= 0 { + out[idx] = e.payload.val + } + }) +} + +func (h *Float64HashTable) WriteOut(out []byte) { + h.WriteOutSubset(0, out) +} + +func (h *Float64HashTable) WriteOutSubset(start int, out []byte) { + data := arrow.Float64Traits.CastFromBytes(out) + h.VisitEntries(func(e *entryFloat64) { + idx := e.payload.memoIdx - int32(start) + if idx >= 0 { + data[idx] = utils.ToLEFloat64(e.payload.val) + } + }) +} + +func (h *Float64HashTable) needUpsize() bool { return h.size*uint64(loadFactor) >= h.cap } + +func (Float64HashTable) fixHash(v uint64) uint64 { + if v == sentinel { + return 42 + } + return v +} + +// Lookup retrieves the entry for a given hash value assuming it's payload value returns +// true when passed to the cmp func. Returns a pointer to the entry for the given hash value, +// and a boolean as to whether it was found. It is not safe to use the pointer if the bool is false. +func (h *Float64HashTable) Lookup(v uint64, cmp func(float64) bool) (*entryFloat64, bool) { + idx, ok := h.lookup(v, h.capMask, cmp) + return &h.entries[idx], ok +} + +func (h *Float64HashTable) lookup(v uint64, szMask uint64, cmp func(float64) bool) (uint64, bool) { + const perturbShift uint8 = 5 + + var ( + idx uint64 + perturb uint64 + e *entryFloat64 + ) + + v = h.fixHash(v) + idx = v & szMask + perturb = (v >> uint64(perturbShift)) + 1 + + for { + e = &h.entries[idx] + if e.h == v && cmp(e.payload.val) { + return idx, true + } + + if e.h == sentinel { + return idx, false + } + + // perturbation logic inspired from CPython's set/dict object + // the goal is that all 64 bits of unmasked hash value eventually + // participate int he probing sequence, to minimize clustering + idx = (idx + perturb) & szMask + perturb = (perturb >> uint64(perturbShift)) + 1 + } +} + +func (h *Float64HashTable) upsize(newcap uint64) error { + newMask := newcap - 1 + + oldEntries := h.entries + h.entries = make([]entryFloat64, newcap) + for _, e := range oldEntries { + if e.Valid() { + idx, _ := h.lookup(e.h, newMask, func(float64) bool { return false }) + h.entries[idx] = e + } + } + h.cap = newcap + h.capMask = newMask + return nil +} + +// Insert updates the given entry with the provided hash value, payload value and memo index. +// The entry pointer must have been retrieved via lookup in order to actually insert properly. +func (h *Float64HashTable) Insert(e *entryFloat64, v uint64, val float64, memoIdx int32) error { + e.h = h.fixHash(v) + e.payload.val = val + e.payload.memoIdx = memoIdx + h.size++ + + if h.needUpsize() { + h.upsize(h.cap * uint64(loadFactor) * 2) + } + return nil +} + +// VisitEntries will call the passed in function on each *valid* entry in the hash table, +// a valid entry being one which has had a value inserted into it. +func (h *Float64HashTable) VisitEntries(visit func(*entryFloat64)) { + for _, e := range h.entries { + if e.Valid() { + visit(&e) + } + } +} + +// Float64MemoTable is a wrapper over the appropriate hashtable to provide an interface +// conforming to the MemoTable interface defined in the encoding package for general interactions +// regarding dictionaries. +type Float64MemoTable struct { + tbl *Float64HashTable + nullIdx int32 +} + +// NewFloat64MemoTable returns a new memotable with num entries pre-allocated to reduce further +// allocations when inserting. +func NewFloat64MemoTable(num int64) *Float64MemoTable { + return &Float64MemoTable{tbl: NewFloat64HashTable(uint64(num)), nullIdx: KeyNotFound} +} + +func (Float64MemoTable) TypeTraits() TypeTraits { + return arrow.Float64Traits +} + +// Reset allows this table to be re-used by dumping all the data currently in the table. +func (s *Float64MemoTable) Reset() { + s.tbl.Reset(32) + s.nullIdx = KeyNotFound +} + +// Size returns the current number of inserted elements into the table including if a null +// has been inserted. +func (s *Float64MemoTable) Size() int { + sz := int(s.tbl.size) + if _, ok := s.GetNull(); ok { + sz++ + } + return sz +} + +// GetNull returns the index of an inserted null or KeyNotFound along with a bool +// that will be true if found and false if not. +func (s *Float64MemoTable) GetNull() (int, bool) { + return int(s.nullIdx), s.nullIdx != KeyNotFound +} + +// GetOrInsertNull will return the index of the null entry or insert a null entry +// if one currently doesn't exist. The found value will be true if there was already +// a null in the table, and false if it inserted one. +func (s *Float64MemoTable) GetOrInsertNull() (idx int, found bool) { + idx, found = s.GetNull() + if !found { + idx = s.Size() + s.nullIdx = int32(idx) + } + return +} + +// CopyValues will copy the values from the memo table out into the passed in slice +// which must be of the appropriate type. +func (s *Float64MemoTable) CopyValues(out interface{}) { + s.CopyValuesSubset(0, out) +} + +// CopyValuesSubset is like CopyValues but only copies a subset of values starting +// at the provided start index +func (s *Float64MemoTable) CopyValuesSubset(start int, out interface{}) { + s.tbl.CopyValuesSubset(start, out.([]float64)) +} + +func (s *Float64MemoTable) WriteOut(out []byte) { + s.tbl.CopyValues(arrow.Float64Traits.CastFromBytes(out)) +} + +func (s *Float64MemoTable) WriteOutSubset(start int, out []byte) { + s.tbl.CopyValuesSubset(start, arrow.Float64Traits.CastFromBytes(out)) +} + +func (s *Float64MemoTable) WriteOutLE(out []byte) { + s.tbl.WriteOut(out) +} + +func (s *Float64MemoTable) WriteOutSubsetLE(start int, out []byte) { + s.tbl.WriteOutSubset(start, out) +} + +// Get returns the index of the requested value in the hash table or KeyNotFound +// along with a boolean indicating if it was found or not. +func (s *Float64MemoTable) Get(val interface{}) (int, bool) { + var cmp func(float64) bool + if math.IsNaN(val.(float64)) { + cmp = math.IsNaN + // use consistent internal bit pattern for NaN regardless of the pattern + // that is passed to us. NaN is NaN is NaN + val = math.NaN() + } else { + cmp = func(v float64) bool { return val.(float64) == v } + } + + h := hashFloat64(val.(float64), 0) + if e, ok := s.tbl.Lookup(h, cmp); ok { + return int(e.payload.memoIdx), ok + } + return KeyNotFound, false +} + +// GetOrInsert will return the index of the specified value in the table, or insert the +// value into the table and return the new index. found indicates whether or not it already +// existed in the table (true) or was inserted by this call (false). +func (s *Float64MemoTable) GetOrInsert(val interface{}) (idx int, found bool, err error) { + + var cmp func(float64) bool + if math.IsNaN(val.(float64)) { + cmp = math.IsNaN + // use consistent internal bit pattern for NaN regardless of the pattern + // that is passed to us. NaN is NaN is NaN + val = math.NaN() + } else { + cmp = func(v float64) bool { return val.(float64) == v } + } + + h := hashFloat64(val.(float64), 0) + e, ok := s.tbl.Lookup(h, cmp) + + if ok { + idx = int(e.payload.memoIdx) + found = true + } else { + idx = s.Size() + s.tbl.Insert(e, h, val.(float64), int32(idx)) + } + return +} + +// GetOrInsertBytes is unimplemented +func (s *Float64MemoTable) GetOrInsertBytes(val []byte) (idx int, found bool, err error) { + panic("unimplemented") +} diff --git a/vendor/github.com/apache/arrow/go/v14/internal/hashing/xxh3_memo_table.gen.go.tmpl b/vendor/github.com/apache/arrow/go/v14/internal/hashing/xxh3_memo_table.gen.go.tmpl new file mode 100644 index 000000000..25164341d --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/hashing/xxh3_memo_table.gen.go.tmpl @@ -0,0 +1,349 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package hashing + +import ( + "github.com/apache/arrow/go/v14/arrow/bitutil" + "github.com/apache/arrow/go/v14/internal/utils" +) + +{{range .In}} +type payload{{.Name}} struct { + val {{.name}} + memoIdx int32 +} + +type entry{{.Name}} struct { + h uint64 + payload payload{{.Name}} +} + +func (e entry{{.Name}}) Valid() bool { return e.h != sentinel } + +// {{.Name}}HashTable is a hashtable specifically for {{.name}} that +// is utilized with the MemoTable to generalize interactions for easier +// implementation of dictionaries without losing performance. +type {{.Name}}HashTable struct { + cap uint64 + capMask uint64 + size uint64 + + entries []entry{{.Name}} +} + +// New{{.Name}}HashTable returns a new hash table for {{.name}} values +// initialized with the passed in capacity or 32 whichever is larger. +func New{{.Name}}HashTable(cap uint64) *{{.Name}}HashTable { + initCap := uint64(bitutil.NextPowerOf2(int(max(cap, 32)))) + ret := &{{.Name}}HashTable{cap: initCap, capMask: initCap - 1, size: 0} + ret.entries = make([]entry{{.Name}}, initCap) + return ret +} + +// Reset drops all of the values in this hash table and re-initializes it +// with the specified initial capacity as if by calling New, but without having +// to reallocate the object. +func (h *{{.Name}}HashTable) Reset(cap uint64) { + h.cap = uint64(bitutil.NextPowerOf2(int(max(cap, 32)))) + h.capMask = h.cap - 1 + h.size = 0 + h.entries = make([]entry{{.Name}}, h.cap) +} + +// CopyValues is used for copying the values out of the hash table into the +// passed in slice, in the order that they were first inserted +func (h *{{.Name}}HashTable) CopyValues(out []{{.name}}) { + h.CopyValuesSubset(0, out) +} + +// CopyValuesSubset copies a subset of the values in the hashtable out, starting +// with the value at start, in the order that they were inserted. +func (h *{{.Name}}HashTable) CopyValuesSubset(start int, out []{{.name}}) { + h.VisitEntries(func(e *entry{{.Name}}) { + idx := e.payload.memoIdx - int32(start) + if idx >= 0 { + out[idx] = e.payload.val + } + }) +} + +func (h *{{.Name}}HashTable) WriteOut(out []byte) { + h.WriteOutSubset(0, out) +} + +func (h *{{.Name}}HashTable) WriteOutSubset(start int, out []byte) { + data := arrow.{{.Name}}Traits.CastFromBytes(out) + h.VisitEntries(func(e *entry{{.Name}}) { + idx := e.payload.memoIdx - int32(start) + if idx >= 0 { +{{if and (ne .Name "Int8") (ne .Name "Uint8") -}} + data[idx] = utils.ToLE{{.Name}}(e.payload.val) +{{else -}} + data[idx] = e.payload.val +{{end -}} + } + }) +} + +func (h *{{.Name}}HashTable) needUpsize() bool { return h.size*uint64(loadFactor) >= h.cap } + +func ({{.Name}}HashTable) fixHash(v uint64) uint64 { + if v == sentinel { + return 42 + } + return v +} + +// Lookup retrieves the entry for a given hash value assuming it's payload value returns +// true when passed to the cmp func. Returns a pointer to the entry for the given hash value, +// and a boolean as to whether it was found. It is not safe to use the pointer if the bool is false. +func (h *{{.Name}}HashTable) Lookup(v uint64, cmp func({{.name}}) bool) (*entry{{.Name}}, bool) { + idx, ok := h.lookup(v, h.capMask, cmp) + return &h.entries[idx], ok +} + +func (h *{{.Name}}HashTable) lookup(v uint64, szMask uint64, cmp func({{.name}}) bool) (uint64, bool) { + const perturbShift uint8 = 5 + + var ( + idx uint64 + perturb uint64 + e *entry{{.Name}} + ) + + v = h.fixHash(v) + idx = v & szMask + perturb = (v >> uint64(perturbShift)) + 1 + + for { + e = &h.entries[idx] + if e.h == v && cmp(e.payload.val) { + return idx, true + } + + if e.h == sentinel { + return idx, false + } + + // perturbation logic inspired from CPython's set/dict object + // the goal is that all 64 bits of unmasked hash value eventually + // participate int he probing sequence, to minimize clustering + idx = (idx + perturb) & szMask + perturb = (perturb >> uint64(perturbShift)) + 1 + } +} + +func (h *{{.Name}}HashTable) upsize(newcap uint64) error { + newMask := newcap - 1 + + oldEntries := h.entries + h.entries = make([]entry{{.Name}}, newcap) + for _, e := range oldEntries { + if e.Valid() { + idx, _ := h.lookup(e.h, newMask, func({{.name}}) bool { return false }) + h.entries[idx] = e + } + } + h.cap = newcap + h.capMask = newMask + return nil +} + +// Insert updates the given entry with the provided hash value, payload value and memo index. +// The entry pointer must have been retrieved via lookup in order to actually insert properly. +func (h *{{.Name}}HashTable) Insert(e *entry{{.Name}}, v uint64, val {{.name}}, memoIdx int32) error { + e.h = h.fixHash(v) + e.payload.val = val + e.payload.memoIdx = memoIdx + h.size++ + + if h.needUpsize() { + h.upsize(h.cap * uint64(loadFactor) * 2) + } + return nil +} + +// VisitEntries will call the passed in function on each *valid* entry in the hash table, +// a valid entry being one which has had a value inserted into it. +func (h *{{.Name}}HashTable) VisitEntries(visit func(*entry{{.Name}})) { + for _, e := range h.entries { + if e.Valid() { + visit(&e) + } + } +} + +// {{.Name}}MemoTable is a wrapper over the appropriate hashtable to provide an interface +// conforming to the MemoTable interface defined in the encoding package for general interactions +// regarding dictionaries. +type {{.Name}}MemoTable struct { + tbl *{{.Name}}HashTable + nullIdx int32 +} + +// New{{.Name}}MemoTable returns a new memotable with num entries pre-allocated to reduce further +// allocations when inserting. +func New{{.Name}}MemoTable(num int64) *{{.Name}}MemoTable { + return &{{.Name}}MemoTable{tbl: New{{.Name}}HashTable(uint64(num)), nullIdx: KeyNotFound} +} + +func ({{.Name}}MemoTable) TypeTraits() TypeTraits { + return arrow.{{.Name}}Traits +} + +// Reset allows this table to be re-used by dumping all the data currently in the table. +func (s *{{.Name}}MemoTable) Reset() { + s.tbl.Reset(32) + s.nullIdx = KeyNotFound +} + +// Size returns the current number of inserted elements into the table including if a null +// has been inserted. +func (s *{{.Name}}MemoTable) Size() int { + sz := int(s.tbl.size) + if _, ok := s.GetNull(); ok { + sz++ + } + return sz +} + +// GetNull returns the index of an inserted null or KeyNotFound along with a bool +// that will be true if found and false if not. +func (s *{{.Name}}MemoTable) GetNull() (int, bool) { + return int(s.nullIdx), s.nullIdx != KeyNotFound +} + +// GetOrInsertNull will return the index of the null entry or insert a null entry +// if one currently doesn't exist. The found value will be true if there was already +// a null in the table, and false if it inserted one. +func (s *{{.Name}}MemoTable) GetOrInsertNull() (idx int, found bool) { + idx, found = s.GetNull() + if !found { + idx = s.Size() + s.nullIdx = int32(idx) + } + return +} + +// CopyValues will copy the values from the memo table out into the passed in slice +// which must be of the appropriate type. +func (s *{{.Name}}MemoTable) CopyValues(out interface{}) { + s.CopyValuesSubset(0, out) +} + +// CopyValuesSubset is like CopyValues but only copies a subset of values starting +// at the provided start index +func (s *{{.Name}}MemoTable) CopyValuesSubset(start int, out interface{}) { + s.tbl.CopyValuesSubset(start, out.([]{{.name}})) +} + +func (s *{{.Name}}MemoTable) WriteOut(out []byte) { + s.tbl.CopyValues(arrow.{{.Name}}Traits.CastFromBytes(out)) +} + +func (s *{{.Name}}MemoTable) WriteOutSubset(start int, out []byte) { + s.tbl.CopyValuesSubset(start, arrow.{{.Name}}Traits.CastFromBytes(out)) +} + +func (s *{{.Name}}MemoTable) WriteOutLE(out []byte) { + s.tbl.WriteOut(out) +} + +func (s *{{.Name}}MemoTable) WriteOutSubsetLE(start int, out []byte) { + s.tbl.WriteOutSubset(start, out) +} + +// Get returns the index of the requested value in the hash table or KeyNotFound +// along with a boolean indicating if it was found or not. +func (s *{{.Name}}MemoTable) Get(val interface{}) (int, bool) { +{{if and (ne .Name "Float32") (ne .Name "Float64") }} + h := hashInt(uint64(val.({{.name}})), 0) + if e, ok := s.tbl.Lookup(h, func(v {{.name}}) bool { return val.({{.name}}) == v }); ok { +{{ else -}} + var cmp func({{.name}}) bool + {{if eq .Name "Float32"}} + if math.IsNaN(float64(val.(float32))) { + cmp = isNan32Cmp + // use consistent internal bit pattern for NaN regardless of the pattern + // that is passed to us. NaN is NaN is NaN + val = float32(math.NaN()) + {{ else -}} + if math.IsNaN(val.(float64)) { + cmp = math.IsNaN + // use consistent internal bit pattern for NaN regardless of the pattern + // that is passed to us. NaN is NaN is NaN + val = math.NaN() + {{end -}} + } else { + cmp = func(v {{.name}}) bool { return val.({{.name}}) == v } + } + + h := hash{{.Name}}(val.({{.name}}), 0) + if e, ok := s.tbl.Lookup(h, cmp); ok { +{{ end -}} + return int(e.payload.memoIdx), ok + } + return KeyNotFound, false +} + +// GetOrInsert will return the index of the specified value in the table, or insert the +// value into the table and return the new index. found indicates whether or not it already +// existed in the table (true) or was inserted by this call (false). +func (s *{{.Name}}MemoTable) GetOrInsert(val interface{}) (idx int, found bool, err error) { + {{if and (ne .Name "Float32") (ne .Name "Float64") }} + h := hashInt(uint64(val.({{.name}})), 0) + e, ok := s.tbl.Lookup(h, func(v {{.name}}) bool { + return val.({{.name}}) == v + }) +{{ else }} + var cmp func({{.name}}) bool + {{if eq .Name "Float32"}} + if math.IsNaN(float64(val.(float32))) { + cmp = isNan32Cmp + // use consistent internal bit pattern for NaN regardless of the pattern + // that is passed to us. NaN is NaN is NaN + val = float32(math.NaN()) + {{ else -}} + if math.IsNaN(val.(float64)) { + cmp = math.IsNaN + // use consistent internal bit pattern for NaN regardless of the pattern + // that is passed to us. NaN is NaN is NaN + val = math.NaN() + {{end -}} + } else { + cmp = func(v {{.name}}) bool { return val.({{.name}}) == v } + } + + h := hash{{.Name}}(val.({{.name}}), 0) + e, ok := s.tbl.Lookup(h, cmp) +{{ end }} + if ok { + idx = int(e.payload.memoIdx) + found = true + } else { + idx = s.Size() + s.tbl.Insert(e, h, val.({{.name}}), int32(idx)) + } + return +} + + +// GetOrInsertBytes is unimplemented +func (s *{{.Name}}MemoTable) GetOrInsertBytes(val []byte) (idx int, found bool, err error) { + panic("unimplemented") +} +{{end}} diff --git a/vendor/github.com/apache/arrow/go/v14/internal/hashing/xxh3_memo_table.go b/vendor/github.com/apache/arrow/go/v14/internal/hashing/xxh3_memo_table.go new file mode 100644 index 000000000..81994f0a8 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/hashing/xxh3_memo_table.go @@ -0,0 +1,443 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package hashing provides utilities for and an implementation of a hash +// table which is more performant than the default go map implementation +// by leveraging xxh3 and some custom hash functions. +package hashing + +import ( + "bytes" + "math" + "reflect" + "unsafe" +) + +//go:generate go run ../../arrow/_tools/tmpl/main.go -i -data=types.tmpldata xxh3_memo_table.gen.go.tmpl + +type TypeTraits interface { + BytesRequired(n int) int +} + +type ByteSlice interface { + Bytes() []byte +} + +// MemoTable interface for hash tables and dictionary encoding. +// +// Values will remember the order they are inserted to generate a valid +// dictionary. +type MemoTable interface { + TypeTraits() TypeTraits + // Reset drops everything in the table allowing it to be reused + Reset() + // Size returns the current number of unique values stored in + // the table, including whether or not a null value has been + // inserted via GetOrInsertNull. + Size() int + // GetOrInsert returns the index of the table the specified value is, + // and a boolean indicating whether or not the value was found in + // the table (if false, the value was inserted). An error is returned + // if val is not the appropriate type for the table. + GetOrInsert(val interface{}) (idx int, existed bool, err error) + // GetOrInsertBytes returns the index of the table the specified value is, + // and a boolean indicating whether or not the value was found in + // the table (if false, the value was inserted). An error is returned + // if val is not the appropriate type for the table. This function is intended to be used by + // the BinaryMemoTable to prevent uncessary allocations of the data when converting from a []byte to interface{}. + GetOrInsertBytes(val []byte) (idx int, existed bool, err error) + // GetOrInsertNull returns the index of the null value in the table, + // inserting one if it hasn't already been inserted. It returns a boolean + // indicating if the null value already existed or not in the table. + GetOrInsertNull() (idx int, existed bool) + // GetNull returns the index of the null value in the table, but does not + // insert one if it doesn't already exist. Will return -1 if it doesn't exist + // indicated by a false value for the boolean. + GetNull() (idx int, exists bool) + // WriteOut copys the unique values of the memotable out to the byte slice + // provided. Must have allocated enough bytes for all the values. + WriteOut(out []byte) + // WriteOutSubset is like WriteOut, but only writes a subset of values + // starting with the index offset. + WriteOutSubset(offset int, out []byte) +} + +type NumericMemoTable interface { + MemoTable + WriteOutLE(out []byte) + WriteOutSubsetLE(offset int, out []byte) +} + +const ( + sentinel uint64 = 0 + loadFactor int64 = 2 +) + +func max(a, b uint64) uint64 { + if a > b { + return a + } + return b +} + +var isNan32Cmp = func(v float32) bool { return math.IsNaN(float64(v)) } + +// KeyNotFound is the constant returned by memo table functions when a key isn't found in the table +const KeyNotFound = -1 + +type BinaryBuilderIFace interface { + Reserve(int) + ReserveData(int) + Retain() + Resize(int) + ResizeData(int) + Release() + DataLen() int + Value(int) []byte + Len() int + AppendNull() + AppendString(string) + Append([]byte) +} + +// BinaryMemoTable is our hashtable for binary data using the BinaryBuilder +// to construct the actual data in an easy to pass around way with minimal copies +// while using a hash table to keep track of the indexes into the dictionary that +// is created as we go. +type BinaryMemoTable struct { + tbl *Int32HashTable + builder BinaryBuilderIFace + nullIdx int +} + +// NewBinaryMemoTable returns a hash table for Binary data, the passed in allocator will +// be utilized for the BinaryBuilder, if nil then memory.DefaultAllocator will be used. +// initial and valuesize can be used to pre-allocate the table to reduce allocations. With +// initial being the initial number of entries to allocate for and valuesize being the starting +// amount of space allocated for writing the actual binary data. +func NewBinaryMemoTable(initial, valuesize int, bldr BinaryBuilderIFace) *BinaryMemoTable { + bldr.Reserve(int(initial)) + datasize := valuesize + if datasize <= 0 { + datasize = initial * 4 + } + bldr.ReserveData(datasize) + return &BinaryMemoTable{tbl: NewInt32HashTable(uint64(initial)), builder: bldr, nullIdx: KeyNotFound} +} + +type unimplementedtraits struct{} + +func (unimplementedtraits) BytesRequired(int) int { panic("unimplemented") } + +func (BinaryMemoTable) TypeTraits() TypeTraits { + return unimplementedtraits{} +} + +// Reset dumps all of the data in the table allowing it to be reutilized. +func (s *BinaryMemoTable) Reset() { + s.tbl.Reset(32) + s.builder.Resize(0) + s.builder.ResizeData(0) + s.builder.Reserve(int(32)) + s.builder.ReserveData(int(32) * 4) + s.nullIdx = KeyNotFound +} + +// GetNull returns the index of a null that has been inserted into the table or +// KeyNotFound. The bool returned will be true if there was a null inserted into +// the table, and false otherwise. +func (s *BinaryMemoTable) GetNull() (int, bool) { + return int(s.nullIdx), s.nullIdx != KeyNotFound +} + +// Size returns the current size of the memo table including the null value +// if one has been inserted. +func (s *BinaryMemoTable) Size() int { + sz := int(s.tbl.size) + if _, ok := s.GetNull(); ok { + sz++ + } + return sz +} + +// helper function to easily return a byte slice for any given value +// regardless of the type if it's a []byte, string, or fulfills the +// ByteSlice interface. +func (BinaryMemoTable) valAsByteSlice(val interface{}) []byte { + switch v := val.(type) { + case []byte: + return v + case ByteSlice: + return v.Bytes() + case string: + var out []byte + h := (*reflect.StringHeader)(unsafe.Pointer(&v)) + s := (*reflect.SliceHeader)(unsafe.Pointer(&out)) + s.Data = h.Data + s.Len = h.Len + s.Cap = h.Len + return out + default: + panic("invalid type for binarymemotable") + } +} + +// helper function to get the hash value regardless of the underlying binary type +func (BinaryMemoTable) getHash(val interface{}) uint64 { + switch v := val.(type) { + case string: + return hashString(v, 0) + case []byte: + return Hash(v, 0) + case ByteSlice: + return Hash(v.Bytes(), 0) + default: + panic("invalid type for binarymemotable") + } +} + +// helper function to append the given value to the builder regardless +// of the underlying binary type. +func (b *BinaryMemoTable) appendVal(val interface{}) { + switch v := val.(type) { + case string: + b.builder.AppendString(v) + case []byte: + b.builder.Append(v) + case ByteSlice: + b.builder.Append(v.Bytes()) + } +} + +func (b *BinaryMemoTable) lookup(h uint64, val []byte) (*entryInt32, bool) { + return b.tbl.Lookup(h, func(i int32) bool { + return bytes.Equal(val, b.builder.Value(int(i))) + }) +} + +// Get returns the index of the specified value in the table or KeyNotFound, +// and a boolean indicating whether it was found in the table. +func (b *BinaryMemoTable) Get(val interface{}) (int, bool) { + if p, ok := b.lookup(b.getHash(val), b.valAsByteSlice(val)); ok { + return int(p.payload.val), ok + } + return KeyNotFound, false +} + +// GetOrInsertBytes returns the index of the given value in the table, if not found +// it is inserted into the table. The return value 'found' indicates whether the value +// was found in the table (true) or inserted (false) along with any possible error. +func (b *BinaryMemoTable) GetOrInsertBytes(val []byte) (idx int, found bool, err error) { + h := Hash(val, 0) + p, found := b.lookup(h, val) + if found { + idx = int(p.payload.val) + } else { + idx = b.Size() + b.builder.Append(val) + b.tbl.Insert(p, h, int32(idx), -1) + } + return +} + +// GetOrInsert returns the index of the given value in the table, if not found +// it is inserted into the table. The return value 'found' indicates whether the value +// was found in the table (true) or inserted (false) along with any possible error. +func (b *BinaryMemoTable) GetOrInsert(val interface{}) (idx int, found bool, err error) { + h := b.getHash(val) + p, found := b.lookup(h, b.valAsByteSlice(val)) + if found { + idx = int(p.payload.val) + } else { + idx = b.Size() + b.appendVal(val) + b.tbl.Insert(p, h, int32(idx), -1) + } + return +} + +// GetOrInsertNull retrieves the index of a null in the table or inserts +// null into the table, returning the index and a boolean indicating if it was +// found in the table (true) or was inserted (false). +func (b *BinaryMemoTable) GetOrInsertNull() (idx int, found bool) { + idx, found = b.GetNull() + if !found { + idx = b.Size() + b.nullIdx = idx + b.builder.AppendNull() + } + return +} + +func (b *BinaryMemoTable) Value(i int) []byte { + return b.builder.Value(i) +} + +// helper function to get the offset into the builder data for a given +// index value. +func (b *BinaryMemoTable) findOffset(idx int) uintptr { + if b.builder.DataLen() == 0 { + // only empty strings, short circuit + return 0 + } + + val := b.builder.Value(idx) + for len(val) == 0 { + idx++ + if idx >= b.builder.Len() { + break + } + val = b.builder.Value(idx) + } + if len(val) != 0 { + return uintptr(unsafe.Pointer(&val[0])) + } + return uintptr(b.builder.DataLen()) + b.findOffset(0) +} + +// CopyOffsets copies the list of offsets into the passed in slice, the offsets +// being the start and end values of the underlying allocated bytes in the builder +// for the individual values of the table. out should be at least sized to Size()+1 +func (b *BinaryMemoTable) CopyOffsets(out []int32) { + b.CopyOffsetsSubset(0, out) +} + +// CopyOffsetsSubset is like CopyOffsets but instead of copying all of the offsets, +// it gets a subset of the offsets in the table starting at the index provided by "start". +func (b *BinaryMemoTable) CopyOffsetsSubset(start int, out []int32) { + if b.builder.Len() <= start { + return + } + + first := b.findOffset(0) + delta := b.findOffset(start) + sz := b.Size() + for i := start; i < sz; i++ { + offset := int32(b.findOffset(i) - delta) + out[i-start] = offset + } + + out[sz-start] = int32(b.builder.DataLen() - (int(delta) - int(first))) +} + +// CopyLargeOffsets copies the list of offsets into the passed in slice, the offsets +// being the start and end values of the underlying allocated bytes in the builder +// for the individual values of the table. out should be at least sized to Size()+1 +func (b *BinaryMemoTable) CopyLargeOffsets(out []int64) { + b.CopyLargeOffsetsSubset(0, out) +} + +// CopyLargeOffsetsSubset is like CopyOffsets but instead of copying all of the offsets, +// it gets a subset of the offsets in the table starting at the index provided by "start". +func (b *BinaryMemoTable) CopyLargeOffsetsSubset(start int, out []int64) { + if b.builder.Len() <= start { + return + } + + first := b.findOffset(0) + delta := b.findOffset(start) + sz := b.Size() + for i := start; i < sz; i++ { + offset := int64(b.findOffset(i) - delta) + out[i-start] = offset + } + + out[sz-start] = int64(b.builder.DataLen() - (int(delta) - int(first))) +} + +// CopyValues copies the raw binary data bytes out, out should be a []byte +// with at least ValuesSize bytes allocated to copy into. +func (b *BinaryMemoTable) CopyValues(out interface{}) { + b.CopyValuesSubset(0, out) +} + +// CopyValuesSubset copies the raw binary data bytes out starting with the value +// at the index start, out should be a []byte with at least ValuesSize bytes allocated +func (b *BinaryMemoTable) CopyValuesSubset(start int, out interface{}) { + if b.builder.Len() <= start { + return + } + + var ( + first = b.findOffset(0) + offset = b.findOffset(int(start)) + length = b.builder.DataLen() - int(offset-first) + ) + + outval := out.([]byte) + copy(outval, b.builder.Value(start)[0:length]) +} + +func (b *BinaryMemoTable) WriteOut(out []byte) { + b.CopyValues(out) +} + +func (b *BinaryMemoTable) WriteOutSubset(start int, out []byte) { + b.CopyValuesSubset(start, out) +} + +// CopyFixedWidthValues exists to cope with the fact that the table doesn't keep +// track of the fixed width when inserting the null value the databuffer holds a +// zero length byte slice for the null value (if found) +func (b *BinaryMemoTable) CopyFixedWidthValues(start, width int, out []byte) { + if start >= b.Size() { + return + } + + null, exists := b.GetNull() + if !exists || null < start { + // nothing to skip, proceed as usual + b.CopyValuesSubset(start, out) + return + } + + var ( + leftOffset = b.findOffset(start) + nullOffset = b.findOffset(null) + leftSize = nullOffset - leftOffset + rightOffset = leftOffset + uintptr(b.ValuesSize()) + ) + + if leftSize > 0 { + copy(out, b.builder.Value(start)[0:leftSize]) + } + + rightSize := rightOffset - nullOffset + if rightSize > 0 { + // skip the null fixed size value + copy(out[int(leftSize)+width:], b.builder.Value(null + 1)[0:rightSize]) + } +} + +// VisitValues exists to run the visitFn on each value currently in the hash table. +func (b *BinaryMemoTable) VisitValues(start int, visitFn func([]byte)) { + for i := int(start); i < b.Size(); i++ { + visitFn(b.builder.Value(i)) + } +} + +// Release is used to tell the underlying builder that it can release the memory allocated +// when the reference count reaches 0, this is safe to be called from multiple goroutines +// simultaneously +func (b *BinaryMemoTable) Release() { b.builder.Release() } + +// Retain increases the ref count, it is safe to call it from multiple goroutines +// simultaneously. +func (b *BinaryMemoTable) Retain() { b.builder.Retain() } + +// ValuesSize returns the current total size of all the raw bytes that have been inserted +// into the memotable so far. +func (b *BinaryMemoTable) ValuesSize() int { return b.builder.DataLen() } diff --git a/vendor/github.com/apache/arrow/go/v14/internal/json/json.go b/vendor/github.com/apache/arrow/go/v14/internal/json/json.go new file mode 100644 index 000000000..319b12c55 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/json/json.go @@ -0,0 +1,51 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !tinygo +// +build !tinygo + +package json + +import ( + "io" + + "github.com/goccy/go-json" +) + +type Decoder = json.Decoder +type Encoder = json.Encoder +type Marshaler = json.Marshaler +type Delim = json.Delim +type UnmarshalTypeError = json.UnmarshalTypeError +type Number = json.Number +type Unmarshaler = json.Unmarshaler +type RawMessage = json.RawMessage + +func Marshal(v interface{}) ([]byte, error) { + return json.Marshal(v) +} + +func Unmarshal(data []byte, v interface{}) error { + return json.Unmarshal(data, v) +} + +func NewDecoder(r io.Reader) *Decoder { + return json.NewDecoder(r) +} + +func NewEncoder(w io.Writer) *Encoder { + return json.NewEncoder(w) +} diff --git a/vendor/github.com/apache/arrow/go/v14/internal/json/json_tinygo.go b/vendor/github.com/apache/arrow/go/v14/internal/json/json_tinygo.go new file mode 100644 index 000000000..8e4f447b3 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/json/json_tinygo.go @@ -0,0 +1,51 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build tinygo +// +build tinygo + +package json + +import ( + "io" + + "encoding/json" +) + +type Decoder = json.Decoder +type Encoder = json.Encoder +type Marshaler = json.Marshaler +type Delim = json.Delim +type UnmarshalTypeError = json.UnmarshalTypeError +type Number = json.Number +type Unmarshaler = json.Unmarshaler +type RawMessage = json.RawMessage + +func Marshal(v interface{}) ([]byte, error) { + return json.Marshal(v) +} + +func Unmarshal(data []byte, v interface{}) error { + return json.Unmarshal(data, v) +} + +func NewDecoder(r io.Reader) *Decoder { + return json.NewDecoder(r) +} + +func NewEncoder(w io.Writer) *Encoder { + return json.NewEncoder(w) +} diff --git a/vendor/github.com/apache/arrow/go/v14/internal/utils/Makefile b/vendor/github.com/apache/arrow/go/v14/internal/utils/Makefile new file mode 100644 index 000000000..fded9d1d5 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/utils/Makefile @@ -0,0 +1,80 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# this converts rotate instructions from "ro[lr] " -> "ro[lr] , 1" for yasm compatibility +PERL_FIXUP_ROTATE=perl -i -pe 's/(ro[rl]\s+\w{2,3})$$/\1, 1/' + +C2GOASM=c2goasm +CC=clang-11 +C_FLAGS=-target x86_64-unknown-none -masm=intel -mno-red-zone -mstackrealign -mllvm -inline-threshold=1000 \ + -fno-asynchronous-unwind-tables -fno-exceptions -fno-rtti -O3 -fno-builtin -ffast-math -fno-jump-tables -I_lib +ASM_FLAGS_AVX2=-mavx2 -mfma +ASM_FLAGS_SSE4=-msse4 +ASM_FLAGS_BMI2=-mbmi2 +ASM_FLAGS_POPCNT=-mpopcnt + +C_FLAGS_NEON=-O3 -fvectorize -mllvm -force-vector-width=16 -fno-asynchronous-unwind-tables -mno-red-zone -mstackrealign -fno-exceptions \ + -fno-rtti -fno-builtin -ffast-math -fno-jump-tables -I_lib + +GO_SOURCES := $(shell find . -path ./_lib -prune -o -name '*.go' -not -name '*_test.go') +ALL_SOURCES := $(shell find . -path ./_lib -prune -o -name '*.go' -name '*.s' -not -name '*_test.go') + +.PHONEY: assembly + +INTEL_SOURCES := \ + min_max_avx2_amd64.s min_max_sse4_amd64.s transpose_ints_avx2_amd64.s transpose_ints_sse4_amd64.s + +# +# ARROW-15336: DO NOT add the assembly target for Arm64 (ARM_SOURCES) until c2goasm added the Arm64 support. +# min_max_neon_arm64.s was generated by asm2plan9s. +# And manually formatted it as the Arm64 Plan9. +# + +assembly: $(INTEL_SOURCES) + +_lib/min_max_avx2_amd64.s: _lib/min_max.c + $(CC) -S $(C_FLAGS) $(ASM_FLAGS_AVX2) $^ -o $@ ; $(PERL_FIXUP_ROTATE) $@ + +_lib/min_max_sse4_amd64.s: _lib/min_max.c + $(CC) -S $(C_FLAGS) $(ASM_FLAGS_SSE4) $^ -o $@ ; $(PERL_FIXUP_ROTATE) $@ + +_lib/min_max_neon.s: _lib/min_max.c + $(CC) -S $(C_FLAGS_NEON) $^ -o $@ ; $(PERL_FIXUP_ROTATE) $@ + +_lib/transpose_ints_avx2_amd64.s: _lib/transpose_ints.c + $(CC) -S $(C_FLAGS) $(ASM_FLAGS_AVX2) $^ -o $@ ; $(PERL_FIXUP_ROTATE) $@ + +_lib/transpose_ints_sse4_amd64.s: _lib/transpose_ints.c + $(CC) -S $(C_FLAGS) $(ASM_FLAGS_SSE4) $^ -o $@ ; $(PERL_FIXUP_ROTATE) $@ + +_lib/transpose_ints_neon.s: _lib/transpose_ints.c + $(CC) -S $(C_FLAGS_NEON) $^ -o $@ ; $(PERL_FIXUP_ROTATE) $@ + +min_max_avx2_amd64.s: _lib/min_max_avx2_amd64.s + $(C2GOASM) -a -f $^ $@ + +min_max_sse4_amd64.s: _lib/min_max_sse4_amd64.s + $(C2GOASM) -a -f $^ $@ + +transpose_ints_avx2_amd64.s: _lib/transpose_ints_avx2_amd64.s + $(C2GOASM) -a -f $^ $@ + +transpose_ints_sse4_amd64.s: _lib/transpose_ints_sse4_amd64.s + $(C2GOASM) -a -f $^ $@ + +clean: + rm -f $(INTEL_SOURCES) + rm -f $(addprefix _lib/,$(INTEL_SOURCES)) diff --git a/vendor/github.com/apache/arrow/go/v14/internal/utils/buf_reader.go b/vendor/github.com/apache/arrow/go/v14/internal/utils/buf_reader.go new file mode 100644 index 000000000..0b2381da1 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/utils/buf_reader.go @@ -0,0 +1,212 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package utils + +import ( + "bufio" + "errors" + "fmt" + "io" +) + +// bufferedReader is similar to bufio.Reader except +// it will expand the buffer if necessary when asked to Peek +// more bytes than are in the buffer +type bufferedReader struct { + bufferSz int + buf []byte + r, w int + rd io.Reader + err error +} + +// NewBufferedReader returns a buffered reader with similar semantics to bufio.Reader +// except Peek will expand the internal buffer if needed rather than return +// an error. +func NewBufferedReader(rd io.Reader, sz int) *bufferedReader { + // if rd is already a buffered reader whose buffer is >= the requested size + // then just return it as is. no need to make a new object. + b, ok := rd.(*bufferedReader) + if ok && len(b.buf) >= sz { + return b + } + + r := &bufferedReader{ + rd: rd, + } + r.resizeBuffer(sz) + return r +} + +func (b *bufferedReader) resetBuffer() { + if b.buf == nil { + b.buf = make([]byte, b.bufferSz) + } else if b.bufferSz > cap(b.buf) { + buf := b.buf + b.buf = make([]byte, b.bufferSz) + copy(b.buf, buf) + } else { + b.buf = b.buf[:b.bufferSz] + } +} + +func (b *bufferedReader) resizeBuffer(newSize int) { + b.bufferSz = newSize + b.resetBuffer() +} + +func (b *bufferedReader) fill() error { + // slide existing data to the beginning + if b.r > 0 { + copy(b.buf, b.buf[b.r:b.w]) + b.w -= b.r + b.r = 0 + } + + if b.w >= len(b.buf) { + return fmt.Errorf("arrow/bufferedreader: %w", bufio.ErrBufferFull) + } + + n, err := io.ReadAtLeast(b.rd, b.buf[b.w:], 1) + if n < 0 { + return fmt.Errorf("arrow/bufferedreader: filling buffer: %w", bufio.ErrNegativeCount) + } + + b.w += n + b.err = err + return nil +} + +func (b *bufferedReader) readErr() error { + err := b.err + b.err = nil + return err +} + +// Buffered returns the number of bytes currently buffered +func (b *bufferedReader) Buffered() int { return b.w - b.r } + +// SetBufferSize resets the size of the internal buffer to the desired size. +// Will return an error if newSize is <= 0 or if newSize is less than the size +// of the buffered data. +func (b *bufferedReader) SetBufferSize(newSize int) error { + if newSize <= 0 { + return errors.New("buffer size should be positive") + } + + if b.w >= newSize { + return errors.New("cannot shrink read buffer if buffered data remains") + } + + b.resizeBuffer(newSize) + return nil +} + +// Peek will buffer and return n bytes from the underlying reader without advancing +// the reader itself. If n is larger than the current buffer size, the buffer will +// be expanded to accommodate the extra bytes rather than error. +func (b *bufferedReader) Peek(n int) ([]byte, error) { + if n < 0 { + return nil, fmt.Errorf("arrow/bufferedreader: %w", bufio.ErrNegativeCount) + } + + if n > len(b.buf) { + if err := b.SetBufferSize(n); err != nil { + return nil, err + } + } + + for b.w-b.r < n && b.w-b.r < len(b.buf) && b.err == nil { + b.fill() // b.w-b.r < len(b.buf) => buffer is not full + } + + return b.buf[b.r : b.r+n], b.readErr() +} + +// Discard skips the next n bytes either by advancing the internal buffer +// or by reading that many bytes in and throwing them away. +func (b *bufferedReader) Discard(n int) (discarded int, err error) { + if n < 0 { + return 0, fmt.Errorf("arrow/bufferedreader: %w", bufio.ErrNegativeCount) + } + + if n == 0 { + return + } + + remain := n + for { + skip := b.Buffered() + if skip == 0 { + b.fill() + skip = b.Buffered() + } + if skip > remain { + skip = remain + } + b.r += skip + remain -= skip + if remain == 0 { + return n, nil + } + if b.err != nil { + return n - remain, b.readErr() + } + } +} + +func (b *bufferedReader) Read(p []byte) (n int, err error) { + n = len(p) + if n == 0 { + if b.Buffered() > 0 { + return 0, nil + } + return 0, b.readErr() + } + + if b.r == b.w { + if b.err != nil { + return 0, b.readErr() + } + if len(p) >= len(b.buf) { + // large read, empty buffer + // read directly into p to avoid extra copy + n, b.err = b.rd.Read(p) + if n < 0 { + return n, fmt.Errorf("arrow/bufferedreader: %w", bufio.ErrNegativeCount) + } + return n, b.readErr() + } + + // one read + // don't use b.fill + b.r, b.w = 0, 0 + n, b.err = b.rd.Read(b.buf) + if n < 0 { + return n, fmt.Errorf("arrow/bufferedreader: %w", bufio.ErrNegativeCount) + } + if n == 0 { + return 0, b.readErr() + } + b.w += n + } + + // copy as much as we can + n = copy(p, b.buf[b.r:b.w]) + b.r += n + return n, nil +} diff --git a/vendor/github.com/apache/arrow/go/v14/internal/utils/endians_default.go b/vendor/github.com/apache/arrow/go/v14/internal/utils/endians_default.go new file mode 100644 index 000000000..5fd257f52 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/utils/endians_default.go @@ -0,0 +1,30 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !s390x + +package utils + +var ( + ToLEInt16 = func(x int16) int16 { return x } + ToLEUint16 = func(x uint16) uint16 { return x } + ToLEUint32 = func(x uint32) uint32 { return x } + ToLEUint64 = func(x uint64) uint64 { return x } + ToLEInt32 = func(x int32) int32 { return x } + ToLEInt64 = func(x int64) int64 { return x } + ToLEFloat32 = func(x float32) float32 { return x } + ToLEFloat64 = func(x float64) float64 { return x } +) diff --git a/vendor/github.com/apache/arrow/go/v14/internal/utils/endians_s390x.go b/vendor/github.com/apache/arrow/go/v14/internal/utils/endians_s390x.go new file mode 100644 index 000000000..7bb27cd81 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/utils/endians_s390x.go @@ -0,0 +1,33 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package utils + +import ( + "math" + "math/bits" +) + +var ( + ToLEInt16 = func(x int16) int16 { return int16(bits.ReverseBytes16(uint16(x))) } + ToLEUint16 = bits.ReverseBytes16 + ToLEUint32 = bits.ReverseBytes32 + ToLEUint64 = bits.ReverseBytes64 + ToLEInt32 = func(x int32) int32 { return int32(bits.ReverseBytes32(uint32(x))) } + ToLEInt64 = func(x int64) int64 { return int64(bits.ReverseBytes64(uint64(x))) } + ToLEFloat32 = func(x float32) float32 { return math.Float32frombits(bits.ReverseBytes32(math.Float32bits(x))) } + ToLEFloat64 = func(x float64) float64 { return math.Float64frombits(bits.ReverseBytes64(math.Float64bits(x))) } +) diff --git a/vendor/github.com/apache/arrow/go/v14/internal/utils/math.go b/vendor/github.com/apache/arrow/go/v14/internal/utils/math.go new file mode 100644 index 000000000..62cf96ce4 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/utils/math.go @@ -0,0 +1,49 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package utils + +// Min is a convenience Min function for int64 +func Min(a, b int64) int64 { + if a < b { + return a + } + return b +} + +// MinInt is a convenience Min function for int +func MinInt(a, b int) int { + if a < b { + return a + } + return b +} + +// Max is a convenience Max function for int64 +func Max(a, b int64) int64 { + if a > b { + return a + } + return b +} + +// MaxInt is a convenience Max function for int +func MaxInt(a, b int) int { + if a > b { + return a + } + return b +} diff --git a/vendor/github.com/apache/arrow/go/v14/internal/utils/min_max.go b/vendor/github.com/apache/arrow/go/v14/internal/utils/min_max.go new file mode 100644 index 000000000..3d7b0024a --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/utils/min_max.go @@ -0,0 +1,212 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package utils + +import ( + "math" +) + +// this file contains pure go implementations of the min_max functions that are +// SIMD accelerated so that we can fallback to these if the cpu doesn't support +// AVX2 or SSE4 instructions. + +func int8MinMax(values []int8) (min, max int8) { + min = math.MaxInt8 + max = math.MinInt8 + + for _, v := range values { + if min > v { + min = v + } + if max < v { + max = v + } + } + return +} + +func uint8MinMax(values []uint8) (min, max uint8) { + min = math.MaxUint8 + max = 0 + + for _, v := range values { + if min > v { + min = v + } + if max < v { + max = v + } + } + return +} + +func int16MinMax(values []int16) (min, max int16) { + min = math.MaxInt16 + max = math.MinInt16 + + for _, v := range values { + if min > v { + min = v + } + if max < v { + max = v + } + } + return +} + +func uint16MinMax(values []uint16) (min, max uint16) { + min = math.MaxUint16 + max = 0 + + for _, v := range values { + if min > v { + min = v + } + if max < v { + max = v + } + } + return +} + +func int32MinMax(values []int32) (min, max int32) { + min = math.MaxInt32 + max = math.MinInt32 + + for _, v := range values { + if min > v { + min = v + } + if max < v { + max = v + } + } + return +} + +func uint32MinMax(values []uint32) (min, max uint32) { + min = math.MaxUint32 + max = 0 + + for _, v := range values { + if min > v { + min = v + } + if max < v { + max = v + } + } + return +} + +func int64MinMax(values []int64) (min, max int64) { + min = math.MaxInt64 + max = math.MinInt64 + + for _, v := range values { + if min > v { + min = v + } + if max < v { + max = v + } + } + return +} + +func uint64MinMax(values []uint64) (min, max uint64) { + min = math.MaxUint64 + max = 0 + + for _, v := range values { + if min > v { + min = v + } + if max < v { + max = v + } + } + return +} + +var minmaxFuncs = struct { + i8 func([]int8) (int8, int8) + ui8 func([]uint8) (uint8, uint8) + i16 func([]int16) (int16, int16) + ui16 func([]uint16) (uint16, uint16) + i32 func([]int32) (int32, int32) + ui32 func([]uint32) (uint32, uint32) + i64 func([]int64) (int64, int64) + ui64 func([]uint64) (uint64, uint64) +}{} + +// GetMinMaxInt8 returns the min and max for a int8 slice, using AVX2 or +// SSE4 cpu extensions if available, falling back to a pure go implementation +// if they are unavailable or built with the noasm tag. +func GetMinMaxInt8(v []int8) (min, max int8) { + return minmaxFuncs.i8(v) +} + +// GetMinMaxUint8 returns the min and max for a uint8 slice, using AVX2 or +// SSE4 cpu extensions if available, falling back to a pure go implementation +// if they are unavailable or built with the noasm tag. +func GetMinMaxUint8(v []uint8) (min, max uint8) { + return minmaxFuncs.ui8(v) +} + +// GetMinMaxInt16 returns the min and max for a int16 slice, using AVX2 or +// SSE4 cpu extensions if available, falling back to a pure go implementation +// if they are unavailable or built with the noasm tag. +func GetMinMaxInt16(v []int16) (min, max int16) { + return minmaxFuncs.i16(v) +} + +// GetMinMaxUint16 returns the min and max for a uint16 slice, using AVX2 or +// SSE4 cpu extensions if available, falling back to a pure go implementation +// if they are unavailable or built with the noasm tag. +func GetMinMaxUint16(v []uint16) (min, max uint16) { + return minmaxFuncs.ui16(v) +} + +// GetMinMaxInt32 returns the min and max for a int32 slice, using AVX2 or +// SSE4 cpu extensions if available, falling back to a pure go implementation +// if they are unavailable or built with the noasm tag. +func GetMinMaxInt32(v []int32) (min, max int32) { + return minmaxFuncs.i32(v) +} + +// GetMinMaxUint32 returns the min and max for a uint32 slice, using AVX2 or +// SSE4 cpu extensions if available, falling back to a pure go implementation +// if they are unavailable or built with the noasm tag. +func GetMinMaxUint32(v []uint32) (min, max uint32) { + return minmaxFuncs.ui32(v) +} + +// GetMinMaxInt64 returns the min and max for a int64 slice, using AVX2 or +// SSE4 cpu extensions if available, falling back to a pure go implementation +// if they are unavailable or built with the noasm tag. +func GetMinMaxInt64(v []int64) (min, max int64) { + return minmaxFuncs.i64(v) +} + +// GetMinMaxUint64 returns the min and max for a uint64 slice, using AVX2 or +// SSE4 cpu extensions if available, falling back to a pure go implementation +// if they are unavailable or built with the noasm tag. +func GetMinMaxUint64(v []uint64) (min, max uint64) { + return minmaxFuncs.ui64(v) +} diff --git a/vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_amd64.go b/vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_amd64.go new file mode 100644 index 000000000..5fccddbee --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_amd64.go @@ -0,0 +1,55 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !noasm + +package utils + +import "golang.org/x/sys/cpu" + +func init() { + // if the CPU supports AVX2 or SSE4 then let's use those to benefit from SIMD + // to accelerate the performance for finding the min and max for an integral slice. + // otherwise fallback to a pure go implementation if the cpu doesn't have these features. + if cpu.X86.HasAVX2 { + minmaxFuncs.i8 = int8MaxMinAVX2 + minmaxFuncs.ui8 = uint8MaxMinAVX2 + minmaxFuncs.i16 = int16MaxMinAVX2 + minmaxFuncs.ui16 = uint16MaxMinAVX2 + minmaxFuncs.i32 = int32MaxMinAVX2 + minmaxFuncs.ui32 = uint32MaxMinAVX2 + minmaxFuncs.i64 = int64MaxMinAVX2 + minmaxFuncs.ui64 = uint64MaxMinAVX2 + } else if cpu.X86.HasSSE42 { + minmaxFuncs.i8 = int8MaxMinSSE4 + minmaxFuncs.ui8 = uint8MaxMinSSE4 + minmaxFuncs.i16 = int16MaxMinSSE4 + minmaxFuncs.ui16 = uint16MaxMinSSE4 + minmaxFuncs.i32 = int32MaxMinSSE4 + minmaxFuncs.ui32 = uint32MaxMinSSE4 + minmaxFuncs.i64 = int64MaxMinSSE4 + minmaxFuncs.ui64 = uint64MaxMinSSE4 + } else { + minmaxFuncs.i8 = int8MinMax + minmaxFuncs.ui8 = uint8MinMax + minmaxFuncs.i16 = int16MinMax + minmaxFuncs.ui16 = uint16MinMax + minmaxFuncs.i32 = int32MinMax + minmaxFuncs.ui32 = uint32MinMax + minmaxFuncs.i64 = int64MinMax + minmaxFuncs.ui64 = uint64MinMax + } +} diff --git a/vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_arm64.go b/vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_arm64.go new file mode 100644 index 000000000..7404e95d9 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_arm64.go @@ -0,0 +1,65 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !noasm + +package utils + +import ( + "os" + "strings" +) +import "golang.org/x/sys/cpu" + +func init() { + // Added ability to enable extension via environment: + // ARM_ENABLE_EXT=NEON go test + if ext, ok := os.LookupEnv("ARM_ENABLE_EXT"); ok { + exts := strings.Split(ext, ",") + + for _, x := range exts { + switch x { + case "NEON": + cpu.ARM64.HasASIMD = true + case "AES": + cpu.ARM64.HasAES = true + case "PMULL": + cpu.ARM64.HasPMULL = true + default: + cpu.ARM64.HasASIMD = false + cpu.ARM64.HasAES = false + cpu.ARM64.HasPMULL = false + } + } + } + if cpu.ARM64.HasASIMD { + minmaxFuncs.i32 = int32MaxMinNEON + minmaxFuncs.ui32 = uint32MaxMinNEON + minmaxFuncs.i64 = int64MaxMinNEON + minmaxFuncs.ui64 = uint64MaxMinNEON + } else { + minmaxFuncs.i32 = int32MinMax + minmaxFuncs.ui32 = uint32MinMax + minmaxFuncs.i64 = int64MinMax + minmaxFuncs.ui64 = uint64MinMax + } + + // haven't yet generated the NEON arm64 for these + minmaxFuncs.i8 = int8MinMax + minmaxFuncs.ui8 = uint8MinMax + minmaxFuncs.i16 = int16MinMax + minmaxFuncs.ui16 = uint16MinMax +} diff --git a/vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_avx2_amd64.go b/vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_avx2_amd64.go new file mode 100644 index 000000000..af6726243 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_avx2_amd64.go @@ -0,0 +1,90 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !noasm + +package utils + +import ( + "unsafe" +) + +// This file contains convenience functions for utilizing AVX2 intrinsics to quickly +// and efficiently get the min and max from an integral slice. + +//go:noescape +func _int8_max_min_avx2(values unsafe.Pointer, length int, minout, maxout unsafe.Pointer) + +func int8MaxMinAVX2(values []int8) (min, max int8) { + _int8_max_min_avx2(unsafe.Pointer(&values[0]), len(values), unsafe.Pointer(&min), unsafe.Pointer(&max)) + return +} + +//go:noescape +func _uint8_max_min_avx2(values unsafe.Pointer, length int, minout, maxout unsafe.Pointer) + +func uint8MaxMinAVX2(values []uint8) (min, max uint8) { + _uint8_max_min_avx2(unsafe.Pointer(&values[0]), len(values), unsafe.Pointer(&min), unsafe.Pointer(&max)) + return +} + +//go:noescape +func _int16_max_min_avx2(values unsafe.Pointer, length int, minout, maxout unsafe.Pointer) + +func int16MaxMinAVX2(values []int16) (min, max int16) { + _int16_max_min_avx2(unsafe.Pointer(&values[0]), len(values), unsafe.Pointer(&min), unsafe.Pointer(&max)) + return +} + +//go:noescape +func _uint16_max_min_avx2(values unsafe.Pointer, length int, minout, maxout unsafe.Pointer) + +func uint16MaxMinAVX2(values []uint16) (min, max uint16) { + _uint16_max_min_avx2(unsafe.Pointer(&values[0]), len(values), unsafe.Pointer(&min), unsafe.Pointer(&max)) + return +} + +//go:noescape +func _int32_max_min_avx2(values unsafe.Pointer, length int, minout, maxout unsafe.Pointer) + +func int32MaxMinAVX2(values []int32) (min, max int32) { + _int32_max_min_avx2(unsafe.Pointer(&values[0]), len(values), unsafe.Pointer(&min), unsafe.Pointer(&max)) + return +} + +//go:noescape +func _uint32_max_min_avx2(values unsafe.Pointer, length int, minout, maxout unsafe.Pointer) + +func uint32MaxMinAVX2(values []uint32) (min, max uint32) { + _uint32_max_min_avx2(unsafe.Pointer(&values[0]), len(values), unsafe.Pointer(&min), unsafe.Pointer(&max)) + return +} + +//go:noescape +func _int64_max_min_avx2(values unsafe.Pointer, length int, minout, maxout unsafe.Pointer) + +func int64MaxMinAVX2(values []int64) (min, max int64) { + _int64_max_min_avx2(unsafe.Pointer(&values[0]), len(values), unsafe.Pointer(&min), unsafe.Pointer(&max)) + return +} + +//go:noescape +func _uint64_max_min_avx2(values unsafe.Pointer, length int, minout, maxout unsafe.Pointer) + +func uint64MaxMinAVX2(values []uint64) (min, max uint64) { + _uint64_max_min_avx2(unsafe.Pointer(&values[0]), len(values), unsafe.Pointer(&min), unsafe.Pointer(&max)) + return +} diff --git a/vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_avx2_amd64.s b/vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_avx2_amd64.s new file mode 100644 index 000000000..fe0c36e0e --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_avx2_amd64.s @@ -0,0 +1,927 @@ +//+build !noasm !appengine +// AUTO-GENERATED BY C2GOASM -- DO NOT EDIT + +DATA LCDATA1<>+0x000(SB)/8, $0x8080808080808080 +DATA LCDATA1<>+0x008(SB)/8, $0x8080808080808080 +DATA LCDATA1<>+0x010(SB)/8, $0x8080808080808080 +DATA LCDATA1<>+0x018(SB)/8, $0x8080808080808080 +DATA LCDATA1<>+0x020(SB)/8, $0x7f7f7f7f7f7f7f7f +DATA LCDATA1<>+0x028(SB)/8, $0x7f7f7f7f7f7f7f7f +DATA LCDATA1<>+0x030(SB)/8, $0x7f7f7f7f7f7f7f7f +DATA LCDATA1<>+0x038(SB)/8, $0x7f7f7f7f7f7f7f7f +DATA LCDATA1<>+0x040(SB)/8, $0x7f7f7f7f7f7f7f7f +DATA LCDATA1<>+0x048(SB)/8, $0x7f7f7f7f7f7f7f7f +DATA LCDATA1<>+0x050(SB)/8, $0x8080808080808080 +DATA LCDATA1<>+0x058(SB)/8, $0x8080808080808080 +GLOBL LCDATA1<>(SB), 8, $96 + +TEXT ·_int8_max_min_avx2(SB), $0-32 + + MOVQ values+0(FP), DI + MOVQ length+8(FP), SI + MOVQ minout+16(FP), DX + MOVQ maxout+24(FP), CX + LEAQ LCDATA1<>(SB), BP + + WORD $0xf685 // test esi, esi + JLE LBB0_1 + WORD $0x8941; BYTE $0xf1 // mov r9d, esi + WORD $0xfe83; BYTE $0x3f // cmp esi, 63 + JA LBB0_4 + WORD $0xb041; BYTE $0x80 // mov r8b, -128 + WORD $0xb640; BYTE $0x7f // mov sil, 127 + WORD $0x3145; BYTE $0xd2 // xor r10d, r10d + JMP LBB0_11 + +LBB0_1: + WORD $0xb640; BYTE $0x7f // mov sil, 127 + WORD $0xb041; BYTE $0x80 // mov r8b, -128 + JMP LBB0_12 + +LBB0_4: + WORD $0x8945; BYTE $0xca // mov r10d, r9d + LONG $0xc0e28341 // and r10d, -64 + LONG $0xc0428d49 // lea rax, [r10 - 64] + WORD $0x8949; BYTE $0xc0 // mov r8, rax + LONG $0x06e8c149 // shr r8, 6 + LONG $0x01c08349 // add r8, 1 + WORD $0x8548; BYTE $0xc0 // test rax, rax + JE LBB0_5 + WORD $0x894c; BYTE $0xc6 // mov rsi, r8 + LONG $0xfee68348 // and rsi, -2 + WORD $0xf748; BYTE $0xde // neg rsi + LONG $0x4d6ffdc5; BYTE $0x00 // vmovdqa ymm1, yword 0[rbp] /* [rip + .LCPI0_0] */ + LONG $0x456ffdc5; BYTE $0x20 // vmovdqa ymm0, yword 32[rbp] /* [rip + .LCPI0_1] */ + WORD $0xc031 // xor eax, eax + LONG $0xd06ffdc5 // vmovdqa ymm2, ymm0 + LONG $0xd96ffdc5 // vmovdqa ymm3, ymm1 + +LBB0_7: + LONG $0x246ffec5; BYTE $0x07 // vmovdqu ymm4, yword [rdi + rax] + LONG $0x6c6ffec5; WORD $0x2007 // vmovdqu ymm5, yword [rdi + rax + 32] + LONG $0x746ffec5; WORD $0x4007 // vmovdqu ymm6, yword [rdi + rax + 64] + LONG $0x7c6ffec5; WORD $0x6007 // vmovdqu ymm7, yword [rdi + rax + 96] + LONG $0x387de2c4; BYTE $0xc4 // vpminsb ymm0, ymm0, ymm4 + LONG $0x386de2c4; BYTE $0xd5 // vpminsb ymm2, ymm2, ymm5 + LONG $0x3c75e2c4; BYTE $0xcc // vpmaxsb ymm1, ymm1, ymm4 + LONG $0x3c65e2c4; BYTE $0xdd // vpmaxsb ymm3, ymm3, ymm5 + LONG $0x387de2c4; BYTE $0xc6 // vpminsb ymm0, ymm0, ymm6 + LONG $0x386de2c4; BYTE $0xd7 // vpminsb ymm2, ymm2, ymm7 + LONG $0x3c75e2c4; BYTE $0xce // vpmaxsb ymm1, ymm1, ymm6 + LONG $0x3c65e2c4; BYTE $0xdf // vpmaxsb ymm3, ymm3, ymm7 + LONG $0x80e88348 // sub rax, -128 + LONG $0x02c68348 // add rsi, 2 + JNE LBB0_7 + LONG $0x01c0f641 // test r8b, 1 + JE LBB0_10 + +LBB0_9: + LONG $0x246ffec5; BYTE $0x07 // vmovdqu ymm4, yword [rdi + rax] + LONG $0x6c6ffec5; WORD $0x2007 // vmovdqu ymm5, yword [rdi + rax + 32] + LONG $0x3c65e2c4; BYTE $0xdd // vpmaxsb ymm3, ymm3, ymm5 + LONG $0x3c75e2c4; BYTE $0xcc // vpmaxsb ymm1, ymm1, ymm4 + LONG $0x386de2c4; BYTE $0xd5 // vpminsb ymm2, ymm2, ymm5 + LONG $0x387de2c4; BYTE $0xc4 // vpminsb ymm0, ymm0, ymm4 + +LBB0_10: + LONG $0x3c75e2c4; BYTE $0xcb // vpmaxsb ymm1, ymm1, ymm3 + LONG $0x397de3c4; WORD $0x01cb // vextracti128 xmm3, ymm1, 1 + LONG $0x3c71e2c4; BYTE $0xcb // vpmaxsb xmm1, xmm1, xmm3 + LONG $0x4deff1c5; BYTE $0x40 // vpxor xmm1, xmm1, oword 64[rbp] /* [rip + .LCPI0_2] */ + LONG $0x387de2c4; BYTE $0xc2 // vpminsb ymm0, ymm0, ymm2 + LONG $0xd171e9c5; BYTE $0x08 // vpsrlw xmm2, xmm1, 8 + LONG $0xcadaf1c5 // vpminub xmm1, xmm1, xmm2 + LONG $0x4179e2c4; BYTE $0xc9 // vphminposuw xmm1, xmm1 + LONG $0x7e79c1c4; BYTE $0xc8 // vmovd r8d, xmm1 + LONG $0x7ff08041 // xor r8b, 127 + LONG $0x397de3c4; WORD $0x01c1 // vextracti128 xmm1, ymm0, 1 + LONG $0x3879e2c4; BYTE $0xc1 // vpminsb xmm0, xmm0, xmm1 + LONG $0x45eff9c5; BYTE $0x50 // vpxor xmm0, xmm0, oword 80[rbp] /* [rip + .LCPI0_3] */ + LONG $0xd071f1c5; BYTE $0x08 // vpsrlw xmm1, xmm0, 8 + LONG $0xc1daf9c5 // vpminub xmm0, xmm0, xmm1 + LONG $0x4179e2c4; BYTE $0xc0 // vphminposuw xmm0, xmm0 + LONG $0xc67ef9c5 // vmovd esi, xmm0 + LONG $0x80f68040 // xor sil, -128 + WORD $0x394d; BYTE $0xca // cmp r10, r9 + JE LBB0_12 + +LBB0_11: + LONG $0x04b60f42; BYTE $0x17 // movzx eax, byte [rdi + r10] + WORD $0x3840; BYTE $0xc6 // cmp sil, al + LONG $0xf6b60f40 // movzx esi, sil + WORD $0x4f0f; BYTE $0xf0 // cmovg esi, eax + WORD $0x3841; BYTE $0xc0 // cmp r8b, al + LONG $0xc0b60f45 // movzx r8d, r8b + LONG $0xc04c0f44 // cmovl r8d, eax + LONG $0x01c28349 // add r10, 1 + WORD $0x394d; BYTE $0xd1 // cmp r9, r10 + JNE LBB0_11 + +LBB0_12: + WORD $0x8844; BYTE $0x01 // mov byte [rcx], r8b + WORD $0x8840; BYTE $0x32 // mov byte [rdx], sil + VZEROUPPER + RET + +LBB0_5: + LONG $0x4d6ffdc5; BYTE $0x00 // vmovdqa ymm1, yword 0[rbp] /* [rip + .LCPI0_0] */ + LONG $0x456ffdc5; BYTE $0x20 // vmovdqa ymm0, yword 32[rbp] /* [rip + .LCPI0_1] */ + WORD $0xc031 // xor eax, eax + LONG $0xd06ffdc5 // vmovdqa ymm2, ymm0 + LONG $0xd96ffdc5 // vmovdqa ymm3, ymm1 + LONG $0x01c0f641 // test r8b, 1 + JNE LBB0_9 + JMP LBB0_10 + +TEXT ·_uint8_max_min_avx2(SB), $0-32 + + MOVQ values+0(FP), DI + MOVQ length+8(FP), SI + MOVQ minout+16(FP), DX + MOVQ maxout+24(FP), CX + + WORD $0xf685 // test esi, esi + JLE LBB1_1 + WORD $0x8941; BYTE $0xf1 // mov r9d, esi + WORD $0xfe83; BYTE $0x3f // cmp esi, 63 + JA LBB1_4 + WORD $0xb640; BYTE $0xff // mov sil, -1 + WORD $0x3145; BYTE $0xd2 // xor r10d, r10d + WORD $0xc031 // xor eax, eax + JMP LBB1_11 + +LBB1_1: + WORD $0xb640; BYTE $0xff // mov sil, -1 + WORD $0xc031 // xor eax, eax + JMP LBB1_12 + +LBB1_4: + WORD $0x8945; BYTE $0xca // mov r10d, r9d + LONG $0xc0e28341 // and r10d, -64 + LONG $0xc0428d49 // lea rax, [r10 - 64] + WORD $0x8949; BYTE $0xc0 // mov r8, rax + LONG $0x06e8c149 // shr r8, 6 + LONG $0x01c08349 // add r8, 1 + WORD $0x8548; BYTE $0xc0 // test rax, rax + JE LBB1_5 + WORD $0x894c; BYTE $0xc6 // mov rsi, r8 + LONG $0xfee68348 // and rsi, -2 + WORD $0xf748; BYTE $0xde // neg rsi + LONG $0xc0eff9c5 // vpxor xmm0, xmm0, xmm0 + LONG $0xc976f5c5 // vpcmpeqd ymm1, ymm1, ymm1 + WORD $0xc031 // xor eax, eax + LONG $0xd276edc5 // vpcmpeqd ymm2, ymm2, ymm2 + LONG $0xdbefe1c5 // vpxor xmm3, xmm3, xmm3 + +LBB1_7: + LONG $0x246ffec5; BYTE $0x07 // vmovdqu ymm4, yword [rdi + rax] + LONG $0x6c6ffec5; WORD $0x2007 // vmovdqu ymm5, yword [rdi + rax + 32] + LONG $0x746ffec5; WORD $0x4007 // vmovdqu ymm6, yword [rdi + rax + 64] + LONG $0x7c6ffec5; WORD $0x6007 // vmovdqu ymm7, yword [rdi + rax + 96] + LONG $0xccdaf5c5 // vpminub ymm1, ymm1, ymm4 + LONG $0xd5daedc5 // vpminub ymm2, ymm2, ymm5 + LONG $0xc4defdc5 // vpmaxub ymm0, ymm0, ymm4 + LONG $0xdddee5c5 // vpmaxub ymm3, ymm3, ymm5 + LONG $0xcedaf5c5 // vpminub ymm1, ymm1, ymm6 + LONG $0xd7daedc5 // vpminub ymm2, ymm2, ymm7 + LONG $0xc6defdc5 // vpmaxub ymm0, ymm0, ymm6 + LONG $0xdfdee5c5 // vpmaxub ymm3, ymm3, ymm7 + LONG $0x80e88348 // sub rax, -128 + LONG $0x02c68348 // add rsi, 2 + JNE LBB1_7 + LONG $0x01c0f641 // test r8b, 1 + JE LBB1_10 + +LBB1_9: + LONG $0x246ffec5; BYTE $0x07 // vmovdqu ymm4, yword [rdi + rax] + LONG $0x6c6ffec5; WORD $0x2007 // vmovdqu ymm5, yword [rdi + rax + 32] + LONG $0xdddee5c5 // vpmaxub ymm3, ymm3, ymm5 + LONG $0xc4defdc5 // vpmaxub ymm0, ymm0, ymm4 + LONG $0xd5daedc5 // vpminub ymm2, ymm2, ymm5 + LONG $0xccdaf5c5 // vpminub ymm1, ymm1, ymm4 + +LBB1_10: + LONG $0xcadaf5c5 // vpminub ymm1, ymm1, ymm2 + LONG $0xc3defdc5 // vpmaxub ymm0, ymm0, ymm3 + LONG $0x397de3c4; WORD $0x01c2 // vextracti128 xmm2, ymm0, 1 + LONG $0xc2def9c5 // vpmaxub xmm0, xmm0, xmm2 + LONG $0xd276e9c5 // vpcmpeqd xmm2, xmm2, xmm2 + LONG $0xc2eff9c5 // vpxor xmm0, xmm0, xmm2 + LONG $0xd071e9c5; BYTE $0x08 // vpsrlw xmm2, xmm0, 8 + LONG $0xc2daf9c5 // vpminub xmm0, xmm0, xmm2 + LONG $0x4179e2c4; BYTE $0xc0 // vphminposuw xmm0, xmm0 + LONG $0xc07ef9c5 // vmovd eax, xmm0 + WORD $0xd0f6 // not al + LONG $0x397de3c4; WORD $0x01c8 // vextracti128 xmm0, ymm1, 1 + LONG $0xc0daf1c5 // vpminub xmm0, xmm1, xmm0 + LONG $0xd071f1c5; BYTE $0x08 // vpsrlw xmm1, xmm0, 8 + LONG $0xc1daf9c5 // vpminub xmm0, xmm0, xmm1 + LONG $0x4179e2c4; BYTE $0xc0 // vphminposuw xmm0, xmm0 + LONG $0xc67ef9c5 // vmovd esi, xmm0 + WORD $0x394d; BYTE $0xca // cmp r10, r9 + JE LBB1_12 + +LBB1_11: + LONG $0x04b60f46; BYTE $0x17 // movzx r8d, byte [rdi + r10] + WORD $0x3844; BYTE $0xc6 // cmp sil, r8b + LONG $0xf6b60f40 // movzx esi, sil + LONG $0xf0430f41 // cmovae esi, r8d + WORD $0x3844; BYTE $0xc0 // cmp al, r8b + WORD $0xb60f; BYTE $0xc0 // movzx eax, al + LONG $0xc0460f41 // cmovbe eax, r8d + LONG $0x01c28349 // add r10, 1 + WORD $0x394d; BYTE $0xd1 // cmp r9, r10 + JNE LBB1_11 + +LBB1_12: + WORD $0x0188 // mov byte [rcx], al + WORD $0x8840; BYTE $0x32 // mov byte [rdx], sil + VZEROUPPER + RET + +LBB1_5: + LONG $0xc0eff9c5 // vpxor xmm0, xmm0, xmm0 + LONG $0xc976f5c5 // vpcmpeqd ymm1, ymm1, ymm1 + WORD $0xc031 // xor eax, eax + LONG $0xd276edc5 // vpcmpeqd ymm2, ymm2, ymm2 + LONG $0xdbefe1c5 // vpxor xmm3, xmm3, xmm3 + LONG $0x01c0f641 // test r8b, 1 + JNE LBB1_9 + JMP LBB1_10 + +DATA LCDATA2<>+0x000(SB)/8, $0x8000800080008000 +DATA LCDATA2<>+0x008(SB)/8, $0x8000800080008000 +DATA LCDATA2<>+0x010(SB)/8, $0x8000800080008000 +DATA LCDATA2<>+0x018(SB)/8, $0x8000800080008000 +DATA LCDATA2<>+0x020(SB)/8, $0x7fff7fff7fff7fff +DATA LCDATA2<>+0x028(SB)/8, $0x7fff7fff7fff7fff +DATA LCDATA2<>+0x030(SB)/8, $0x7fff7fff7fff7fff +DATA LCDATA2<>+0x038(SB)/8, $0x7fff7fff7fff7fff +DATA LCDATA2<>+0x040(SB)/8, $0x7fff7fff7fff7fff +DATA LCDATA2<>+0x048(SB)/8, $0x7fff7fff7fff7fff +DATA LCDATA2<>+0x050(SB)/8, $0x8000800080008000 +DATA LCDATA2<>+0x058(SB)/8, $0x8000800080008000 +GLOBL LCDATA2<>(SB), 8, $96 + +TEXT ·_int16_max_min_avx2(SB), $0-32 + + MOVQ values+0(FP), DI + MOVQ length+8(FP), SI + MOVQ minout+16(FP), DX + MOVQ maxout+24(FP), CX + LEAQ LCDATA2<>(SB), BP + + WORD $0xf685 // test esi, esi + JLE LBB2_1 + WORD $0x8941; BYTE $0xf1 // mov r9d, esi + WORD $0xfe83; BYTE $0x1f // cmp esi, 31 + JA LBB2_4 + LONG $0x00b84166; BYTE $0x80 // mov r8w, -32768 + LONG $0x7fffbe66 // mov si, 32767 + WORD $0x3145; BYTE $0xd2 // xor r10d, r10d + JMP LBB2_11 + +LBB2_1: + LONG $0x7fffbe66 // mov si, 32767 + LONG $0x00b84166; BYTE $0x80 // mov r8w, -32768 + JMP LBB2_12 + +LBB2_4: + WORD $0x8945; BYTE $0xca // mov r10d, r9d + LONG $0xe0e28341 // and r10d, -32 + LONG $0xe0428d49 // lea rax, [r10 - 32] + WORD $0x8949; BYTE $0xc0 // mov r8, rax + LONG $0x05e8c149 // shr r8, 5 + LONG $0x01c08349 // add r8, 1 + WORD $0x8548; BYTE $0xc0 // test rax, rax + JE LBB2_5 + WORD $0x894c; BYTE $0xc6 // mov rsi, r8 + LONG $0xfee68348 // and rsi, -2 + WORD $0xf748; BYTE $0xde // neg rsi + LONG $0x4d6ffdc5; BYTE $0x00 // vmovdqa ymm1, yword 0[rbp] /* [rip + .LCPI2_0] */ + LONG $0x456ffdc5; BYTE $0x20 // vmovdqa ymm0, yword 32[rbp] /* [rip + .LCPI2_1] */ + WORD $0xc031 // xor eax, eax + LONG $0xd06ffdc5 // vmovdqa ymm2, ymm0 + LONG $0xd96ffdc5 // vmovdqa ymm3, ymm1 + +LBB2_7: + LONG $0x246ffec5; BYTE $0x47 // vmovdqu ymm4, yword [rdi + 2*rax] + LONG $0x6c6ffec5; WORD $0x2047 // vmovdqu ymm5, yword [rdi + 2*rax + 32] + LONG $0x746ffec5; WORD $0x4047 // vmovdqu ymm6, yword [rdi + 2*rax + 64] + LONG $0x7c6ffec5; WORD $0x6047 // vmovdqu ymm7, yword [rdi + 2*rax + 96] + LONG $0xc4eafdc5 // vpminsw ymm0, ymm0, ymm4 + LONG $0xd5eaedc5 // vpminsw ymm2, ymm2, ymm5 + LONG $0xcceef5c5 // vpmaxsw ymm1, ymm1, ymm4 + LONG $0xddeee5c5 // vpmaxsw ymm3, ymm3, ymm5 + LONG $0xc6eafdc5 // vpminsw ymm0, ymm0, ymm6 + LONG $0xd7eaedc5 // vpminsw ymm2, ymm2, ymm7 + LONG $0xceeef5c5 // vpmaxsw ymm1, ymm1, ymm6 + LONG $0xdfeee5c5 // vpmaxsw ymm3, ymm3, ymm7 + LONG $0x40c08348 // add rax, 64 + LONG $0x02c68348 // add rsi, 2 + JNE LBB2_7 + LONG $0x01c0f641 // test r8b, 1 + JE LBB2_10 + +LBB2_9: + LONG $0x246ffec5; BYTE $0x47 // vmovdqu ymm4, yword [rdi + 2*rax] + LONG $0x6c6ffec5; WORD $0x2047 // vmovdqu ymm5, yword [rdi + 2*rax + 32] + LONG $0xddeee5c5 // vpmaxsw ymm3, ymm3, ymm5 + LONG $0xcceef5c5 // vpmaxsw ymm1, ymm1, ymm4 + LONG $0xd5eaedc5 // vpminsw ymm2, ymm2, ymm5 + LONG $0xc4eafdc5 // vpminsw ymm0, ymm0, ymm4 + +LBB2_10: + LONG $0xcbeef5c5 // vpmaxsw ymm1, ymm1, ymm3 + LONG $0x397de3c4; WORD $0x01cb // vextracti128 xmm3, ymm1, 1 + LONG $0xcbeef1c5 // vpmaxsw xmm1, xmm1, xmm3 + LONG $0x4deff1c5; BYTE $0x40 // vpxor xmm1, xmm1, oword 64[rbp] /* [rip + .LCPI2_2] */ + LONG $0xc2eafdc5 // vpminsw ymm0, ymm0, ymm2 + LONG $0x4179e2c4; BYTE $0xc9 // vphminposuw xmm1, xmm1 + LONG $0x7e79c1c4; BYTE $0xc8 // vmovd r8d, xmm1 + LONG $0xfff08141; WORD $0x007f; BYTE $0x00 // xor r8d, 32767 + LONG $0x397de3c4; WORD $0x01c1 // vextracti128 xmm1, ymm0, 1 + LONG $0xc1eaf9c5 // vpminsw xmm0, xmm0, xmm1 + LONG $0x45eff9c5; BYTE $0x50 // vpxor xmm0, xmm0, oword 80[rbp] /* [rip + .LCPI2_3] */ + LONG $0x4179e2c4; BYTE $0xc0 // vphminposuw xmm0, xmm0 + LONG $0xc67ef9c5 // vmovd esi, xmm0 + LONG $0x8000f681; WORD $0x0000 // xor esi, 32768 + WORD $0x394d; BYTE $0xca // cmp r10, r9 + JE LBB2_12 + +LBB2_11: + LONG $0x04b70f42; BYTE $0x57 // movzx eax, word [rdi + 2*r10] + WORD $0x3966; BYTE $0xc6 // cmp si, ax + WORD $0x4f0f; BYTE $0xf0 // cmovg esi, eax + LONG $0xc0394166 // cmp r8w, ax + LONG $0xc04c0f44 // cmovl r8d, eax + LONG $0x01c28349 // add r10, 1 + WORD $0x394d; BYTE $0xd1 // cmp r9, r10 + JNE LBB2_11 + +LBB2_12: + LONG $0x01894466 // mov word [rcx], r8w + WORD $0x8966; BYTE $0x32 // mov word [rdx], si + VZEROUPPER + RET + +LBB2_5: + LONG $0x4d6ffdc5; BYTE $0x00 // vmovdqa ymm1, yword 0[rbp] /* [rip + .LCPI2_0] */ + LONG $0x456ffdc5; BYTE $0x20 // vmovdqa ymm0, yword 32[rbp] /* [rip + .LCPI2_1] */ + WORD $0xc031 // xor eax, eax + LONG $0xd06ffdc5 // vmovdqa ymm2, ymm0 + LONG $0xd96ffdc5 // vmovdqa ymm3, ymm1 + LONG $0x01c0f641 // test r8b, 1 + JNE LBB2_9 + JMP LBB2_10 + +TEXT ·_uint16_max_min_avx2(SB), $0-32 + + MOVQ values+0(FP), DI + MOVQ length+8(FP), SI + MOVQ minout+16(FP), DX + MOVQ maxout+24(FP), CX + + WORD $0xf685 // test esi, esi + JLE LBB3_1 + WORD $0x8941; BYTE $0xf1 // mov r9d, esi + WORD $0xfe83; BYTE $0x1f // cmp esi, 31 + JA LBB3_4 + LONG $0xffb84166; BYTE $0xff // mov r8w, -1 + WORD $0x3145; BYTE $0xd2 // xor r10d, r10d + WORD $0xf631 // xor esi, esi + JMP LBB3_11 + +LBB3_1: + LONG $0xffb84166; BYTE $0xff // mov r8w, -1 + WORD $0xf631 // xor esi, esi + JMP LBB3_12 + +LBB3_4: + WORD $0x8945; BYTE $0xca // mov r10d, r9d + LONG $0xe0e28341 // and r10d, -32 + LONG $0xe0428d49 // lea rax, [r10 - 32] + WORD $0x8949; BYTE $0xc0 // mov r8, rax + LONG $0x05e8c149 // shr r8, 5 + LONG $0x01c08349 // add r8, 1 + WORD $0x8548; BYTE $0xc0 // test rax, rax + JE LBB3_5 + WORD $0x894c; BYTE $0xc6 // mov rsi, r8 + LONG $0xfee68348 // and rsi, -2 + WORD $0xf748; BYTE $0xde // neg rsi + LONG $0xc0eff9c5 // vpxor xmm0, xmm0, xmm0 + LONG $0xc976f5c5 // vpcmpeqd ymm1, ymm1, ymm1 + WORD $0xc031 // xor eax, eax + LONG $0xd276edc5 // vpcmpeqd ymm2, ymm2, ymm2 + LONG $0xdbefe1c5 // vpxor xmm3, xmm3, xmm3 + +LBB3_7: + LONG $0x246ffec5; BYTE $0x47 // vmovdqu ymm4, yword [rdi + 2*rax] + LONG $0x6c6ffec5; WORD $0x2047 // vmovdqu ymm5, yword [rdi + 2*rax + 32] + LONG $0x746ffec5; WORD $0x4047 // vmovdqu ymm6, yword [rdi + 2*rax + 64] + LONG $0x7c6ffec5; WORD $0x6047 // vmovdqu ymm7, yword [rdi + 2*rax + 96] + LONG $0x3a75e2c4; BYTE $0xcc // vpminuw ymm1, ymm1, ymm4 + LONG $0x3a6de2c4; BYTE $0xd5 // vpminuw ymm2, ymm2, ymm5 + LONG $0x3e7de2c4; BYTE $0xc4 // vpmaxuw ymm0, ymm0, ymm4 + LONG $0x3e65e2c4; BYTE $0xdd // vpmaxuw ymm3, ymm3, ymm5 + LONG $0x3a75e2c4; BYTE $0xce // vpminuw ymm1, ymm1, ymm6 + LONG $0x3a6de2c4; BYTE $0xd7 // vpminuw ymm2, ymm2, ymm7 + LONG $0x3e7de2c4; BYTE $0xc6 // vpmaxuw ymm0, ymm0, ymm6 + LONG $0x3e65e2c4; BYTE $0xdf // vpmaxuw ymm3, ymm3, ymm7 + LONG $0x40c08348 // add rax, 64 + LONG $0x02c68348 // add rsi, 2 + JNE LBB3_7 + LONG $0x01c0f641 // test r8b, 1 + JE LBB3_10 + +LBB3_9: + LONG $0x246ffec5; BYTE $0x47 // vmovdqu ymm4, yword [rdi + 2*rax] + LONG $0x6c6ffec5; WORD $0x2047 // vmovdqu ymm5, yword [rdi + 2*rax + 32] + LONG $0x3e65e2c4; BYTE $0xdd // vpmaxuw ymm3, ymm3, ymm5 + LONG $0x3e7de2c4; BYTE $0xc4 // vpmaxuw ymm0, ymm0, ymm4 + LONG $0x3a6de2c4; BYTE $0xd5 // vpminuw ymm2, ymm2, ymm5 + LONG $0x3a75e2c4; BYTE $0xcc // vpminuw ymm1, ymm1, ymm4 + +LBB3_10: + LONG $0x3a75e2c4; BYTE $0xca // vpminuw ymm1, ymm1, ymm2 + LONG $0x3e7de2c4; BYTE $0xc3 // vpmaxuw ymm0, ymm0, ymm3 + LONG $0x397de3c4; WORD $0x01c2 // vextracti128 xmm2, ymm0, 1 + LONG $0x3e79e2c4; BYTE $0xc2 // vpmaxuw xmm0, xmm0, xmm2 + LONG $0xd276e9c5 // vpcmpeqd xmm2, xmm2, xmm2 + LONG $0xc2eff9c5 // vpxor xmm0, xmm0, xmm2 + LONG $0x4179e2c4; BYTE $0xc0 // vphminposuw xmm0, xmm0 + LONG $0xc67ef9c5 // vmovd esi, xmm0 + WORD $0xd6f7 // not esi + LONG $0x397de3c4; WORD $0x01c8 // vextracti128 xmm0, ymm1, 1 + LONG $0x3a71e2c4; BYTE $0xc0 // vpminuw xmm0, xmm1, xmm0 + LONG $0x4179e2c4; BYTE $0xc0 // vphminposuw xmm0, xmm0 + LONG $0x7e79c1c4; BYTE $0xc0 // vmovd r8d, xmm0 + WORD $0x394d; BYTE $0xca // cmp r10, r9 + JE LBB3_12 + +LBB3_11: + LONG $0x04b70f42; BYTE $0x57 // movzx eax, word [rdi + 2*r10] + LONG $0xc0394166 // cmp r8w, ax + LONG $0xc0430f44 // cmovae r8d, eax + WORD $0x3966; BYTE $0xc6 // cmp si, ax + WORD $0x460f; BYTE $0xf0 // cmovbe esi, eax + LONG $0x01c28349 // add r10, 1 + WORD $0x394d; BYTE $0xd1 // cmp r9, r10 + JNE LBB3_11 + +LBB3_12: + WORD $0x8966; BYTE $0x31 // mov word [rcx], si + LONG $0x02894466 // mov word [rdx], r8w + VZEROUPPER + RET + +LBB3_5: + LONG $0xc0eff9c5 // vpxor xmm0, xmm0, xmm0 + LONG $0xc976f5c5 // vpcmpeqd ymm1, ymm1, ymm1 + WORD $0xc031 // xor eax, eax + LONG $0xd276edc5 // vpcmpeqd ymm2, ymm2, ymm2 + LONG $0xdbefe1c5 // vpxor xmm3, xmm3, xmm3 + LONG $0x01c0f641 // test r8b, 1 + JNE LBB3_9 + JMP LBB3_10 + +DATA LCDATA3<>+0x000(SB)/8, $0x7fffffff80000000 +GLOBL LCDATA3<>(SB), 8, $8 + +TEXT ·_int32_max_min_avx2(SB), $0-32 + + MOVQ values+0(FP), DI + MOVQ length+8(FP), SI + MOVQ minout+16(FP), DX + MOVQ maxout+24(FP), CX + LEAQ LCDATA3<>(SB), BP + + WORD $0xf685 // test esi, esi + JLE LBB4_1 + WORD $0x8941; BYTE $0xf0 // mov r8d, esi + WORD $0xfe83; BYTE $0x1f // cmp esi, 31 + JA LBB4_4 + LONG $0x0000ba41; WORD $0x8000 // mov r10d, -2147483648 + LONG $0xffffffb8; BYTE $0x7f // mov eax, 2147483647 + WORD $0x3145; BYTE $0xc9 // xor r9d, r9d + JMP LBB4_7 + +LBB4_1: + LONG $0xffffffb8; BYTE $0x7f // mov eax, 2147483647 + LONG $0x000000be; BYTE $0x80 // mov esi, -2147483648 + JMP LBB4_8 + +LBB4_4: + WORD $0x8945; BYTE $0xc1 // mov r9d, r8d + LONG $0x587de2c4; WORD $0x0065 // vpbroadcastd ymm4, dword 0[rbp] /* [rip + .LCPI4_0] */ + LONG $0xe0e18341 // and r9d, -32 + LONG $0x587de2c4; WORD $0x0445 // vpbroadcastd ymm0, dword 4[rbp] /* [rip + .LCPI4_1] */ + WORD $0xc031 // xor eax, eax + LONG $0xc86ffdc5 // vmovdqa ymm1, ymm0 + LONG $0xd06ffdc5 // vmovdqa ymm2, ymm0 + LONG $0xd86ffdc5 // vmovdqa ymm3, ymm0 + LONG $0xec6ffdc5 // vmovdqa ymm5, ymm4 + LONG $0xf46ffdc5 // vmovdqa ymm6, ymm4 + LONG $0xfc6ffdc5 // vmovdqa ymm7, ymm4 + +LBB4_5: + LONG $0x046f7ec5; BYTE $0x87 // vmovdqu ymm8, yword [rdi + 4*rax] + LONG $0x4c6f7ec5; WORD $0x2087 // vmovdqu ymm9, yword [rdi + 4*rax + 32] + LONG $0x546f7ec5; WORD $0x4087 // vmovdqu ymm10, yword [rdi + 4*rax + 64] + LONG $0x5c6f7ec5; WORD $0x6087 // vmovdqu ymm11, yword [rdi + 4*rax + 96] + LONG $0x397dc2c4; BYTE $0xc0 // vpminsd ymm0, ymm0, ymm8 + LONG $0x3975c2c4; BYTE $0xc9 // vpminsd ymm1, ymm1, ymm9 + LONG $0x396dc2c4; BYTE $0xd2 // vpminsd ymm2, ymm2, ymm10 + LONG $0x3965c2c4; BYTE $0xdb // vpminsd ymm3, ymm3, ymm11 + LONG $0x3d5dc2c4; BYTE $0xe0 // vpmaxsd ymm4, ymm4, ymm8 + LONG $0x3d55c2c4; BYTE $0xe9 // vpmaxsd ymm5, ymm5, ymm9 + LONG $0x3d4dc2c4; BYTE $0xf2 // vpmaxsd ymm6, ymm6, ymm10 + LONG $0x3d45c2c4; BYTE $0xfb // vpmaxsd ymm7, ymm7, ymm11 + LONG $0x20c08348 // add rax, 32 + WORD $0x3949; BYTE $0xc1 // cmp r9, rax + JNE LBB4_5 + LONG $0x3d5de2c4; BYTE $0xe5 // vpmaxsd ymm4, ymm4, ymm5 + LONG $0x3d5de2c4; BYTE $0xe6 // vpmaxsd ymm4, ymm4, ymm6 + LONG $0x3d5de2c4; BYTE $0xe7 // vpmaxsd ymm4, ymm4, ymm7 + LONG $0x397de3c4; WORD $0x01e5 // vextracti128 xmm5, ymm4, 1 + LONG $0x3d59e2c4; BYTE $0xe5 // vpmaxsd xmm4, xmm4, xmm5 + LONG $0xec70f9c5; BYTE $0x4e // vpshufd xmm5, xmm4, 78 + LONG $0x3d59e2c4; BYTE $0xe5 // vpmaxsd xmm4, xmm4, xmm5 + LONG $0xec70f9c5; BYTE $0xe5 // vpshufd xmm5, xmm4, 229 + LONG $0x3d59e2c4; BYTE $0xe5 // vpmaxsd xmm4, xmm4, xmm5 + LONG $0x7e79c1c4; BYTE $0xe2 // vmovd r10d, xmm4 + LONG $0x397de2c4; BYTE $0xc1 // vpminsd ymm0, ymm0, ymm1 + LONG $0x397de2c4; BYTE $0xc2 // vpminsd ymm0, ymm0, ymm2 + LONG $0x397de2c4; BYTE $0xc3 // vpminsd ymm0, ymm0, ymm3 + LONG $0x397de3c4; WORD $0x01c1 // vextracti128 xmm1, ymm0, 1 + LONG $0x3979e2c4; BYTE $0xc1 // vpminsd xmm0, xmm0, xmm1 + LONG $0xc870f9c5; BYTE $0x4e // vpshufd xmm1, xmm0, 78 + LONG $0x3979e2c4; BYTE $0xc1 // vpminsd xmm0, xmm0, xmm1 + LONG $0xc870f9c5; BYTE $0xe5 // vpshufd xmm1, xmm0, 229 + LONG $0x3979e2c4; BYTE $0xc1 // vpminsd xmm0, xmm0, xmm1 + LONG $0xc07ef9c5 // vmovd eax, xmm0 + WORD $0x8944; BYTE $0xd6 // mov esi, r10d + WORD $0x394d; BYTE $0xc1 // cmp r9, r8 + JE LBB4_8 + +LBB4_7: + LONG $0x8f348b42 // mov esi, dword [rdi + 4*r9] + WORD $0xf039 // cmp eax, esi + WORD $0x4f0f; BYTE $0xc6 // cmovg eax, esi + WORD $0x3941; BYTE $0xf2 // cmp r10d, esi + LONG $0xf24d0f41 // cmovge esi, r10d + LONG $0x01c18349 // add r9, 1 + WORD $0x8941; BYTE $0xf2 // mov r10d, esi + WORD $0x394d; BYTE $0xc8 // cmp r8, r9 + JNE LBB4_7 + +LBB4_8: + WORD $0x3189 // mov dword [rcx], esi + WORD $0x0289 // mov dword [rdx], eax + VZEROUPPER + RET + +TEXT ·_uint32_max_min_avx2(SB), $0-32 + + MOVQ values+0(FP), DI + MOVQ length+8(FP), SI + MOVQ minout+16(FP), DX + MOVQ maxout+24(FP), CX + + WORD $0xf685 // test esi, esi + JLE LBB5_1 + WORD $0x8941; BYTE $0xf0 // mov r8d, esi + WORD $0xfe83; BYTE $0x1f // cmp esi, 31 + JA LBB5_4 + WORD $0x3145; BYTE $0xc9 // xor r9d, r9d + LONG $0xffffffb8; BYTE $0xff // mov eax, -1 + WORD $0x3145; BYTE $0xd2 // xor r10d, r10d + JMP LBB5_7 + +LBB5_1: + LONG $0xffffffb8; BYTE $0xff // mov eax, -1 + WORD $0xf631 // xor esi, esi + JMP LBB5_8 + +LBB5_4: + WORD $0x8945; BYTE $0xc1 // mov r9d, r8d + LONG $0xe0e18341 // and r9d, -32 + LONG $0xe4efd9c5 // vpxor xmm4, xmm4, xmm4 + LONG $0xc076fdc5 // vpcmpeqd ymm0, ymm0, ymm0 + WORD $0xc031 // xor eax, eax + LONG $0xc976f5c5 // vpcmpeqd ymm1, ymm1, ymm1 + LONG $0xd276edc5 // vpcmpeqd ymm2, ymm2, ymm2 + LONG $0xdb76e5c5 // vpcmpeqd ymm3, ymm3, ymm3 + LONG $0xedefd1c5 // vpxor xmm5, xmm5, xmm5 + LONG $0xf6efc9c5 // vpxor xmm6, xmm6, xmm6 + LONG $0xffefc1c5 // vpxor xmm7, xmm7, xmm7 + +LBB5_5: + LONG $0x046f7ec5; BYTE $0x87 // vmovdqu ymm8, yword [rdi + 4*rax] + LONG $0x4c6f7ec5; WORD $0x2087 // vmovdqu ymm9, yword [rdi + 4*rax + 32] + LONG $0x546f7ec5; WORD $0x4087 // vmovdqu ymm10, yword [rdi + 4*rax + 64] + LONG $0x5c6f7ec5; WORD $0x6087 // vmovdqu ymm11, yword [rdi + 4*rax + 96] + LONG $0x3b7dc2c4; BYTE $0xc0 // vpminud ymm0, ymm0, ymm8 + LONG $0x3b75c2c4; BYTE $0xc9 // vpminud ymm1, ymm1, ymm9 + LONG $0x3b6dc2c4; BYTE $0xd2 // vpminud ymm2, ymm2, ymm10 + LONG $0x3b65c2c4; BYTE $0xdb // vpminud ymm3, ymm3, ymm11 + LONG $0x3f5dc2c4; BYTE $0xe0 // vpmaxud ymm4, ymm4, ymm8 + LONG $0x3f55c2c4; BYTE $0xe9 // vpmaxud ymm5, ymm5, ymm9 + LONG $0x3f4dc2c4; BYTE $0xf2 // vpmaxud ymm6, ymm6, ymm10 + LONG $0x3f45c2c4; BYTE $0xfb // vpmaxud ymm7, ymm7, ymm11 + LONG $0x20c08348 // add rax, 32 + WORD $0x3949; BYTE $0xc1 // cmp r9, rax + JNE LBB5_5 + LONG $0x3f5de2c4; BYTE $0xe5 // vpmaxud ymm4, ymm4, ymm5 + LONG $0x3f5de2c4; BYTE $0xe6 // vpmaxud ymm4, ymm4, ymm6 + LONG $0x3f5de2c4; BYTE $0xe7 // vpmaxud ymm4, ymm4, ymm7 + LONG $0x397de3c4; WORD $0x01e5 // vextracti128 xmm5, ymm4, 1 + LONG $0x3f59e2c4; BYTE $0xe5 // vpmaxud xmm4, xmm4, xmm5 + LONG $0xec70f9c5; BYTE $0x4e // vpshufd xmm5, xmm4, 78 + LONG $0x3f59e2c4; BYTE $0xe5 // vpmaxud xmm4, xmm4, xmm5 + LONG $0xec70f9c5; BYTE $0xe5 // vpshufd xmm5, xmm4, 229 + LONG $0x3f59e2c4; BYTE $0xe5 // vpmaxud xmm4, xmm4, xmm5 + LONG $0x7e79c1c4; BYTE $0xe2 // vmovd r10d, xmm4 + LONG $0x3b7de2c4; BYTE $0xc1 // vpminud ymm0, ymm0, ymm1 + LONG $0x3b7de2c4; BYTE $0xc2 // vpminud ymm0, ymm0, ymm2 + LONG $0x3b7de2c4; BYTE $0xc3 // vpminud ymm0, ymm0, ymm3 + LONG $0x397de3c4; WORD $0x01c1 // vextracti128 xmm1, ymm0, 1 + LONG $0x3b79e2c4; BYTE $0xc1 // vpminud xmm0, xmm0, xmm1 + LONG $0xc870f9c5; BYTE $0x4e // vpshufd xmm1, xmm0, 78 + LONG $0x3b79e2c4; BYTE $0xc1 // vpminud xmm0, xmm0, xmm1 + LONG $0xc870f9c5; BYTE $0xe5 // vpshufd xmm1, xmm0, 229 + LONG $0x3b79e2c4; BYTE $0xc1 // vpminud xmm0, xmm0, xmm1 + LONG $0xc07ef9c5 // vmovd eax, xmm0 + WORD $0x8944; BYTE $0xd6 // mov esi, r10d + WORD $0x394d; BYTE $0xc1 // cmp r9, r8 + JE LBB5_8 + +LBB5_7: + LONG $0x8f348b42 // mov esi, dword [rdi + 4*r9] + WORD $0xf039 // cmp eax, esi + WORD $0x430f; BYTE $0xc6 // cmovae eax, esi + WORD $0x3941; BYTE $0xf2 // cmp r10d, esi + LONG $0xf2470f41 // cmova esi, r10d + LONG $0x01c18349 // add r9, 1 + WORD $0x8941; BYTE $0xf2 // mov r10d, esi + WORD $0x394d; BYTE $0xc8 // cmp r8, r9 + JNE LBB5_7 + +LBB5_8: + WORD $0x3189 // mov dword [rcx], esi + WORD $0x0289 // mov dword [rdx], eax + VZEROUPPER + RET + +DATA LCDATA4<>+0x000(SB)/8, $0x8000000000000000 +DATA LCDATA4<>+0x008(SB)/8, $0x7fffffffffffffff +GLOBL LCDATA4<>(SB), 8, $16 + +TEXT ·_int64_max_min_avx2(SB), $0-32 + + MOVQ values+0(FP), DI + MOVQ length+8(FP), SI + MOVQ minout+16(FP), DX + MOVQ maxout+24(FP), CX + LEAQ LCDATA4<>(SB), BP + + QUAD $0xffffffffffffb848; WORD $0x7fff // mov rax, 9223372036854775807 + WORD $0xf685 // test esi, esi + JLE LBB6_1 + WORD $0x8941; BYTE $0xf0 // mov r8d, esi + WORD $0xfe83; BYTE $0x0f // cmp esi, 15 + JA LBB6_4 + LONG $0x01508d4c // lea r10, [rax + 1] + WORD $0x3145; BYTE $0xc9 // xor r9d, r9d + JMP LBB6_7 + +LBB6_1: + LONG $0x01708d48 // lea rsi, [rax + 1] + JMP LBB6_8 + +LBB6_4: + WORD $0x8945; BYTE $0xc1 // mov r9d, r8d + LONG $0x597de2c4; WORD $0x0065 // vpbroadcastq ymm4, qword 0[rbp] /* [rip + .LCPI6_0] */ + LONG $0xf0e18341 // and r9d, -16 + LONG $0x597de2c4; WORD $0x0845 // vpbroadcastq ymm0, qword 8[rbp] /* [rip + .LCPI6_1] */ + WORD $0xc031 // xor eax, eax + LONG $0xd86ffdc5 // vmovdqa ymm3, ymm0 + LONG $0xd06ffdc5 // vmovdqa ymm2, ymm0 + LONG $0xc86ffdc5 // vmovdqa ymm1, ymm0 + LONG $0xfc6ffdc5 // vmovdqa ymm7, ymm4 + LONG $0xf46ffdc5 // vmovdqa ymm6, ymm4 + LONG $0xec6ffdc5 // vmovdqa ymm5, ymm4 + +LBB6_5: + LONG $0x046f7ec5; BYTE $0xc7 // vmovdqu ymm8, yword [rdi + 8*rax] + LONG $0x373d62c4; BYTE $0xc8 // vpcmpgtq ymm9, ymm8, ymm0 + LONG $0x4b3de3c4; WORD $0x90c0 // vblendvpd ymm0, ymm8, ymm0, ymm9 + LONG $0x4c6f7ec5; WORD $0x20c7 // vmovdqu ymm9, yword [rdi + 8*rax + 32] + LONG $0x373562c4; BYTE $0xd3 // vpcmpgtq ymm10, ymm9, ymm3 + LONG $0x4b35e3c4; WORD $0xa0db // vblendvpd ymm3, ymm9, ymm3, ymm10 + LONG $0x546f7ec5; WORD $0x40c7 // vmovdqu ymm10, yword [rdi + 8*rax + 64] + LONG $0x372d62c4; BYTE $0xda // vpcmpgtq ymm11, ymm10, ymm2 + LONG $0x4b2de3c4; WORD $0xb0d2 // vblendvpd ymm2, ymm10, ymm2, ymm11 + LONG $0x5c6f7ec5; WORD $0x60c7 // vmovdqu ymm11, yword [rdi + 8*rax + 96] + LONG $0x372562c4; BYTE $0xe1 // vpcmpgtq ymm12, ymm11, ymm1 + LONG $0x4b25e3c4; WORD $0xc0c9 // vblendvpd ymm1, ymm11, ymm1, ymm12 + LONG $0x375d42c4; BYTE $0xe0 // vpcmpgtq ymm12, ymm4, ymm8 + LONG $0x4b3de3c4; WORD $0xc0e4 // vblendvpd ymm4, ymm8, ymm4, ymm12 + LONG $0x374542c4; BYTE $0xc1 // vpcmpgtq ymm8, ymm7, ymm9 + LONG $0x4b35e3c4; WORD $0x80ff // vblendvpd ymm7, ymm9, ymm7, ymm8 + LONG $0x374d42c4; BYTE $0xc2 // vpcmpgtq ymm8, ymm6, ymm10 + LONG $0x4b2de3c4; WORD $0x80f6 // vblendvpd ymm6, ymm10, ymm6, ymm8 + LONG $0x375542c4; BYTE $0xc3 // vpcmpgtq ymm8, ymm5, ymm11 + LONG $0x4b25e3c4; WORD $0x80ed // vblendvpd ymm5, ymm11, ymm5, ymm8 + LONG $0x10c08348 // add rax, 16 + WORD $0x3949; BYTE $0xc1 // cmp r9, rax + JNE LBB6_5 + LONG $0x375d62c4; BYTE $0xc7 // vpcmpgtq ymm8, ymm4, ymm7 + LONG $0x4b45e3c4; WORD $0x80e4 // vblendvpd ymm4, ymm7, ymm4, ymm8 + LONG $0x375de2c4; BYTE $0xfe // vpcmpgtq ymm7, ymm4, ymm6 + LONG $0x4b4de3c4; WORD $0x70e4 // vblendvpd ymm4, ymm6, ymm4, ymm7 + LONG $0x375de2c4; BYTE $0xf5 // vpcmpgtq ymm6, ymm4, ymm5 + LONG $0x4b55e3c4; WORD $0x60e4 // vblendvpd ymm4, ymm5, ymm4, ymm6 + LONG $0x197de3c4; WORD $0x01e5 // vextractf128 xmm5, ymm4, 1 + LONG $0x3759e2c4; BYTE $0xf5 // vpcmpgtq xmm6, xmm4, xmm5 + LONG $0x4b51e3c4; WORD $0x60e4 // vblendvpd xmm4, xmm5, xmm4, xmm6 + LONG $0x0479e3c4; WORD $0x4eec // vpermilps xmm5, xmm4, 78 + LONG $0x3759e2c4; BYTE $0xf5 // vpcmpgtq xmm6, xmm4, xmm5 + LONG $0x4b51e3c4; WORD $0x60e4 // vblendvpd xmm4, xmm5, xmm4, xmm6 + LONG $0x7ef9c1c4; BYTE $0xe2 // vmovq r10, xmm4 + LONG $0x3765e2c4; BYTE $0xe0 // vpcmpgtq ymm4, ymm3, ymm0 + LONG $0x4b65e3c4; WORD $0x40c0 // vblendvpd ymm0, ymm3, ymm0, ymm4 + LONG $0x376de2c4; BYTE $0xd8 // vpcmpgtq ymm3, ymm2, ymm0 + LONG $0x4b6de3c4; WORD $0x30c0 // vblendvpd ymm0, ymm2, ymm0, ymm3 + LONG $0x3775e2c4; BYTE $0xd0 // vpcmpgtq ymm2, ymm1, ymm0 + LONG $0x4b75e3c4; WORD $0x20c0 // vblendvpd ymm0, ymm1, ymm0, ymm2 + LONG $0x197de3c4; WORD $0x01c1 // vextractf128 xmm1, ymm0, 1 + LONG $0x3771e2c4; BYTE $0xd0 // vpcmpgtq xmm2, xmm1, xmm0 + LONG $0x4b71e3c4; WORD $0x20c0 // vblendvpd xmm0, xmm1, xmm0, xmm2 + LONG $0x0479e3c4; WORD $0x4ec8 // vpermilps xmm1, xmm0, 78 + LONG $0x3771e2c4; BYTE $0xd0 // vpcmpgtq xmm2, xmm1, xmm0 + LONG $0x4b71e3c4; WORD $0x20c0 // vblendvpd xmm0, xmm1, xmm0, xmm2 + LONG $0x7ef9e1c4; BYTE $0xc0 // vmovq rax, xmm0 + WORD $0x894c; BYTE $0xd6 // mov rsi, r10 + WORD $0x394d; BYTE $0xc1 // cmp r9, r8 + JE LBB6_8 + +LBB6_7: + LONG $0xcf348b4a // mov rsi, qword [rdi + 8*r9] + WORD $0x3948; BYTE $0xf0 // cmp rax, rsi + LONG $0xc64f0f48 // cmovg rax, rsi + WORD $0x3949; BYTE $0xf2 // cmp r10, rsi + LONG $0xf24d0f49 // cmovge rsi, r10 + LONG $0x01c18349 // add r9, 1 + WORD $0x8949; BYTE $0xf2 // mov r10, rsi + WORD $0x394d; BYTE $0xc8 // cmp r8, r9 + JNE LBB6_7 + +LBB6_8: + WORD $0x8948; BYTE $0x31 // mov qword [rcx], rsi + WORD $0x8948; BYTE $0x02 // mov qword [rdx], rax + VZEROUPPER + RET + +DATA LCDATA5<>+0x000(SB)/8, $0x8000000000000000 +GLOBL LCDATA5<>(SB), 8, $8 + +TEXT ·_uint64_max_min_avx2(SB), $0-32 + + MOVQ values+0(FP), DI + MOVQ length+8(FP), SI + MOVQ minout+16(FP), DX + MOVQ maxout+24(FP), CX + LEAQ LCDATA5<>(SB), BP + + WORD $0xf685 // test esi, esi + JLE LBB7_1 + WORD $0x8941; BYTE $0xf0 // mov r8d, esi + WORD $0xfe83; BYTE $0x0f // cmp esi, 15 + JA LBB7_4 + LONG $0xffc0c748; WORD $0xffff; BYTE $0xff // mov rax, -1 + WORD $0x3145; BYTE $0xc9 // xor r9d, r9d + WORD $0x3145; BYTE $0xd2 // xor r10d, r10d + JMP LBB7_7 + +LBB7_1: + LONG $0xffc0c748; WORD $0xffff; BYTE $0xff // mov rax, -1 + WORD $0xf631 // xor esi, esi + JMP LBB7_8 + +LBB7_4: + WORD $0x8945; BYTE $0xc1 // mov r9d, r8d + LONG $0xf0e18341 // and r9d, -16 + LONG $0xedefd1c5 // vpxor xmm5, xmm5, xmm5 + LONG $0xc976f5c5 // vpcmpeqd ymm1, ymm1, ymm1 + WORD $0xc031 // xor eax, eax + LONG $0x597de2c4; WORD $0x0045 // vpbroadcastq ymm0, qword 0[rbp] /* [rip + .LCPI7_0] */ + LONG $0xe476ddc5 // vpcmpeqd ymm4, ymm4, ymm4 + LONG $0xdb76e5c5 // vpcmpeqd ymm3, ymm3, ymm3 + LONG $0xd276edc5 // vpcmpeqd ymm2, ymm2, ymm2 + LONG $0xef3941c4; BYTE $0xc0 // vpxor xmm8, xmm8, xmm8 + LONG $0xffefc1c5 // vpxor xmm7, xmm7, xmm7 + LONG $0xf6efc9c5 // vpxor xmm6, xmm6, xmm6 + +LBB7_5: + LONG $0x0c6f7ec5; BYTE $0xc7 // vmovdqu ymm9, yword [rdi + 8*rax] + LONG $0xd0ef75c5 // vpxor ymm10, ymm1, ymm0 + LONG $0xd8ef35c5 // vpxor ymm11, ymm9, ymm0 + LONG $0x372542c4; BYTE $0xd2 // vpcmpgtq ymm10, ymm11, ymm10 + LONG $0x4b35e3c4; WORD $0xa0c9 // vblendvpd ymm1, ymm9, ymm1, ymm10 + LONG $0xd0ef55c5 // vpxor ymm10, ymm5, ymm0 + LONG $0x372d42c4; BYTE $0xd3 // vpcmpgtq ymm10, ymm10, ymm11 + LONG $0x4b35e3c4; WORD $0xa0ed // vblendvpd ymm5, ymm9, ymm5, ymm10 + LONG $0x4c6f7ec5; WORD $0x20c7 // vmovdqu ymm9, yword [rdi + 8*rax + 32] + LONG $0xd0ef5dc5 // vpxor ymm10, ymm4, ymm0 + LONG $0xd8ef35c5 // vpxor ymm11, ymm9, ymm0 + LONG $0x372542c4; BYTE $0xd2 // vpcmpgtq ymm10, ymm11, ymm10 + LONG $0x4b35e3c4; WORD $0xa0e4 // vblendvpd ymm4, ymm9, ymm4, ymm10 + LONG $0xd0ef3dc5 // vpxor ymm10, ymm8, ymm0 + LONG $0x372d42c4; BYTE $0xd3 // vpcmpgtq ymm10, ymm10, ymm11 + LONG $0x5c6f7ec5; WORD $0x40c7 // vmovdqu ymm11, yword [rdi + 8*rax + 64] + LONG $0x4b3543c4; WORD $0xa0c0 // vblendvpd ymm8, ymm9, ymm8, ymm10 + LONG $0xc8ef65c5 // vpxor ymm9, ymm3, ymm0 + LONG $0xd0ef25c5 // vpxor ymm10, ymm11, ymm0 + LONG $0x372d42c4; BYTE $0xc9 // vpcmpgtq ymm9, ymm10, ymm9 + LONG $0x4b25e3c4; WORD $0x90db // vblendvpd ymm3, ymm11, ymm3, ymm9 + LONG $0xc8ef45c5 // vpxor ymm9, ymm7, ymm0 + LONG $0x373542c4; BYTE $0xca // vpcmpgtq ymm9, ymm9, ymm10 + LONG $0x4b25e3c4; WORD $0x90ff // vblendvpd ymm7, ymm11, ymm7, ymm9 + LONG $0x4c6f7ec5; WORD $0x60c7 // vmovdqu ymm9, yword [rdi + 8*rax + 96] + LONG $0xd0ef6dc5 // vpxor ymm10, ymm2, ymm0 + LONG $0xd8ef35c5 // vpxor ymm11, ymm9, ymm0 + LONG $0x372542c4; BYTE $0xd2 // vpcmpgtq ymm10, ymm11, ymm10 + LONG $0x4b35e3c4; WORD $0xa0d2 // vblendvpd ymm2, ymm9, ymm2, ymm10 + LONG $0xd0ef4dc5 // vpxor ymm10, ymm6, ymm0 + LONG $0x372d42c4; BYTE $0xd3 // vpcmpgtq ymm10, ymm10, ymm11 + LONG $0x4b35e3c4; WORD $0xa0f6 // vblendvpd ymm6, ymm9, ymm6, ymm10 + LONG $0x10c08348 // add rax, 16 + WORD $0x3949; BYTE $0xc1 // cmp r9, rax + JNE LBB7_5 + LONG $0xc8ef3dc5 // vpxor ymm9, ymm8, ymm0 + LONG $0xd0ef55c5 // vpxor ymm10, ymm5, ymm0 + LONG $0x372d42c4; BYTE $0xc9 // vpcmpgtq ymm9, ymm10, ymm9 + LONG $0x4b3de3c4; WORD $0x90ed // vblendvpd ymm5, ymm8, ymm5, ymm9 + LONG $0xc05755c5 // vxorpd ymm8, ymm5, ymm0 + LONG $0xc8ef45c5 // vpxor ymm9, ymm7, ymm0 + LONG $0x373d42c4; BYTE $0xc1 // vpcmpgtq ymm8, ymm8, ymm9 + LONG $0x4b45e3c4; WORD $0x80ed // vblendvpd ymm5, ymm7, ymm5, ymm8 + LONG $0xf857d5c5 // vxorpd ymm7, ymm5, ymm0 + LONG $0xc0ef4dc5 // vpxor ymm8, ymm6, ymm0 + LONG $0x3745c2c4; BYTE $0xf8 // vpcmpgtq ymm7, ymm7, ymm8 + LONG $0x4b4de3c4; WORD $0x70ed // vblendvpd ymm5, ymm6, ymm5, ymm7 + LONG $0x197de3c4; WORD $0x01ee // vextractf128 xmm6, ymm5, 1 + LONG $0xc05749c5 // vxorpd xmm8, xmm6, xmm0 + LONG $0xf857d1c5 // vxorpd xmm7, xmm5, xmm0 + LONG $0x3741c2c4; BYTE $0xf8 // vpcmpgtq xmm7, xmm7, xmm8 + LONG $0x4b49e3c4; WORD $0x70ed // vblendvpd xmm5, xmm6, xmm5, xmm7 + LONG $0x0479e3c4; WORD $0x4ef5 // vpermilps xmm6, xmm5, 78 + LONG $0xc05751c5 // vxorpd xmm8, xmm5, xmm0 + LONG $0xf857c9c5 // vxorpd xmm7, xmm6, xmm0 + LONG $0x3739e2c4; BYTE $0xff // vpcmpgtq xmm7, xmm8, xmm7 + LONG $0x4b49e3c4; WORD $0x70ed // vblendvpd xmm5, xmm6, xmm5, xmm7 + LONG $0xf0eff5c5 // vpxor ymm6, ymm1, ymm0 + LONG $0xf8efddc5 // vpxor ymm7, ymm4, ymm0 + LONG $0x3745e2c4; BYTE $0xf6 // vpcmpgtq ymm6, ymm7, ymm6 + LONG $0x4b5de3c4; WORD $0x60c9 // vblendvpd ymm1, ymm4, ymm1, ymm6 + LONG $0xe057f5c5 // vxorpd ymm4, ymm1, ymm0 + LONG $0xf0efe5c5 // vpxor ymm6, ymm3, ymm0 + LONG $0x374de2c4; BYTE $0xe4 // vpcmpgtq ymm4, ymm6, ymm4 + LONG $0x4b65e3c4; WORD $0x40c9 // vblendvpd ymm1, ymm3, ymm1, ymm4 + LONG $0x7ef9c1c4; BYTE $0xea // vmovq r10, xmm5 + LONG $0xd857f5c5 // vxorpd ymm3, ymm1, ymm0 + LONG $0xe0efedc5 // vpxor ymm4, ymm2, ymm0 + LONG $0x375de2c4; BYTE $0xdb // vpcmpgtq ymm3, ymm4, ymm3 + LONG $0x4b6de3c4; WORD $0x30c9 // vblendvpd ymm1, ymm2, ymm1, ymm3 + LONG $0x197de3c4; WORD $0x01ca // vextractf128 xmm2, ymm1, 1 + LONG $0xd857f1c5 // vxorpd xmm3, xmm1, xmm0 + LONG $0xe057e9c5 // vxorpd xmm4, xmm2, xmm0 + LONG $0x3759e2c4; BYTE $0xdb // vpcmpgtq xmm3, xmm4, xmm3 + LONG $0x4b69e3c4; WORD $0x30c9 // vblendvpd xmm1, xmm2, xmm1, xmm3 + LONG $0x0479e3c4; WORD $0x4ed1 // vpermilps xmm2, xmm1, 78 + LONG $0xd857f1c5 // vxorpd xmm3, xmm1, xmm0 + LONG $0xc057e9c5 // vxorpd xmm0, xmm2, xmm0 + LONG $0x3779e2c4; BYTE $0xc3 // vpcmpgtq xmm0, xmm0, xmm3 + LONG $0x4b69e3c4; WORD $0x00c1 // vblendvpd xmm0, xmm2, xmm1, xmm0 + LONG $0x7ef9e1c4; BYTE $0xc0 // vmovq rax, xmm0 + WORD $0x894c; BYTE $0xd6 // mov rsi, r10 + WORD $0x394d; BYTE $0xc1 // cmp r9, r8 + JE LBB7_8 + +LBB7_7: + LONG $0xcf348b4a // mov rsi, qword [rdi + 8*r9] + WORD $0x3948; BYTE $0xf0 // cmp rax, rsi + LONG $0xc6430f48 // cmovae rax, rsi + WORD $0x3949; BYTE $0xf2 // cmp r10, rsi + LONG $0xf2470f49 // cmova rsi, r10 + LONG $0x01c18349 // add r9, 1 + WORD $0x8949; BYTE $0xf2 // mov r10, rsi + WORD $0x394d; BYTE $0xc8 // cmp r8, r9 + JNE LBB7_7 + +LBB7_8: + WORD $0x8948; BYTE $0x31 // mov qword [rcx], rsi + WORD $0x8948; BYTE $0x02 // mov qword [rdx], rax + VZEROUPPER + RET diff --git a/vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_neon_arm64.go b/vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_neon_arm64.go new file mode 100644 index 000000000..f9d3c44e3 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_neon_arm64.go @@ -0,0 +1,56 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !noasm + +package utils + +import "unsafe" + +// This file contains convenience functions for utilizing Arm64 Neon intrinsics to quickly +// and efficiently get the min and max from an integral slice. + +//go:noescape +func _int32_max_min_neon(values unsafe.Pointer, length int, minout, maxout unsafe.Pointer) + +func int32MaxMinNEON(values []int32) (min, max int32) { + _int32_max_min_neon(unsafe.Pointer(&values[0]), len(values), unsafe.Pointer(&min), unsafe.Pointer(&max)) + return +} + +//go:noescape +func _uint32_max_min_neon(values unsafe.Pointer, length int, minout, maxout unsafe.Pointer) + +func uint32MaxMinNEON(values []uint32) (min, max uint32) { + _uint32_max_min_neon(unsafe.Pointer(&values[0]), len(values), unsafe.Pointer(&min), unsafe.Pointer(&max)) + return +} + +//go:noescape +func _int64_max_min_neon(values unsafe.Pointer, length int, minout, maxout unsafe.Pointer) + +func int64MaxMinNEON(values []int64) (min, max int64) { + _int64_max_min_neon(unsafe.Pointer(&values[0]), len(values), unsafe.Pointer(&min), unsafe.Pointer(&max)) + return +} + +//go:noescape +func _uint64_max_min_neon(values unsafe.Pointer, length int, minout, maxout unsafe.Pointer) + +func uint64MaxMinNEON(values []uint64) (min, max uint64) { + _uint64_max_min_neon(unsafe.Pointer(&values[0]), len(values), unsafe.Pointer(&min), unsafe.Pointer(&max)) + return +} diff --git a/vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_neon_arm64.s b/vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_neon_arm64.s new file mode 100644 index 000000000..b679bb6e3 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_neon_arm64.s @@ -0,0 +1,324 @@ +//+build !noasm !appengine + +// ARROW-15336 +// (C2GOASM doesn't work correctly for Arm64) +// Partly GENERATED BY asm2plan9s. + + +// func _int32_max_min_neon(values unsafe.Pointer, length int, minout, maxout unsafe.Pointer) +TEXT ·_int32_max_min_neon(SB), $0-32 + + MOVD values+0(FP), R0 + MOVD length+8(FP), R1 + MOVD minout+16(FP), R2 + MOVD maxout+24(FP), R3 + + WORD $0xa9bf7bfd // stp x29, x30, [sp, #-16]! + WORD $0x7100043f // cmp w1, #1 + WORD $0x910003fd // mov x29, sp + BLT LBB0_3 + + WORD $0x71000c3f // cmp w1, #3 + WORD $0x2a0103e8 // mov w8, w1 + BHI LBB0_4 + + WORD $0xaa1f03e9 // mov x9, xzr + WORD $0x52b0000b // mov w11, #-2147483648 + WORD $0x12b0000a // mov w10, #2147483647 + JMP LBB0_7 +LBB0_3: + WORD $0x12b0000a // mov w10, #2147483647 + WORD $0x52b0000b // mov w11, #-2147483648 + WORD $0xb900006b // str w11, [x3] + WORD $0xb900004a // str w10, [x2] + WORD $0xa8c17bfd // ldp x29, x30, [sp], #16 + RET +LBB0_4: + WORD $0x927e7509 // and x9, x8, #0xfffffffc + WORD $0x9100200a // add x10, x0, #8 + WORD $0x0f046402 // movi v2.2s, #128, lsl #24 + WORD $0x2f046400 // mvni v0.2s, #128, lsl #24 + WORD $0x2f046401 // mvni v1.2s, #128, lsl #24 + WORD $0xaa0903eb // mov x11, x9 + WORD $0x0f046403 // movi v3.2s, #128, lsl #24 +LBB0_5: + WORD $0x6d7f9544 // ldp d4, d5, [x10, #-8] + WORD $0xf100116b // subs x11, x11, #4 + WORD $0x9100414a // add x10, x10, #16 + WORD $0x0ea46c00 // smin v0.2s, v0.2s, v4.2s + WORD $0x0ea56c21 // smin v1.2s, v1.2s, v5.2s + WORD $0x0ea46442 // smax v2.2s, v2.2s, v4.2s + WORD $0x0ea56463 // smax v3.2s, v3.2s, v5.2s + BNE LBB0_5 + + WORD $0x0ea36442 // smax v2.2s, v2.2s, v3.2s + WORD $0x0ea16c00 // smin v0.2s, v0.2s, v1.2s + WORD $0x0e0c0441 // dup v1.2s, v2.s[1] + WORD $0x0e0c0403 // dup v3.2s, v0.s[1] + WORD $0x0ea16441 // smax v1.2s, v2.2s, v1.2s + WORD $0x0ea36c00 // smin v0.2s, v0.2s, v3.2s + WORD $0xeb08013f // cmp x9, x8 + WORD $0x1e26002b // fmov w11, s1 + WORD $0x1e26000a // fmov w10, s0 + BEQ LBB0_9 +LBB0_7: + WORD $0x8b09080c // add x12, x0, x9, lsl #2 + WORD $0xcb090108 // sub x8, x8, x9 +LBB0_8: + WORD $0xb8404589 // ldr w9, [x12], #4 + WORD $0x6b09015f // cmp w10, w9 + WORD $0x1a89b14a // csel w10, w10, w9, lt + WORD $0x6b09017f // cmp w11, w9 + WORD $0x1a89c16b // csel w11, w11, w9, gt + WORD $0xf1000508 // subs x8, x8, #1 + BNE LBB0_8 +LBB0_9: + WORD $0xb900006b // str w11, [x3] + WORD $0xb900004a // str w10, [x2] + WORD $0xa8c17bfd // ldp x29, x30, [sp], #16 + RET + +// func _uint32_max_min_neon(values unsafe.Pointer, length int, minout, maxout unsafe.Pointer) +TEXT ·_uint32_max_min_neon(SB), $0-32 + + MOVD values+0(FP), R0 + MOVD length+8(FP), R1 + MOVD minout+16(FP), R2 + MOVD maxout+24(FP), R3 + + WORD $0xa9bf7bfd // stp x29, x30, [sp, #-16]! + WORD $0x7100043f // cmp w1, #1 + WORD $0x910003fd // mov x29, sp + BLT LBB1_3 + + WORD $0x71000c3f // cmp w1, #3 + WORD $0x2a0103e8 // mov w8, w1 + BHI LBB1_4 + + WORD $0xaa1f03e9 // mov x9, xzr + WORD $0x2a1f03ea // mov w10, wzr + WORD $0x1280000b // mov w11, #-1 + JMP LBB1_7 +LBB1_3: + WORD $0x2a1f03ea // mov w10, wzr + WORD $0x1280000b // mov w11, #-1 + WORD $0xb900006a // str w10, [x3] + WORD $0xb900004b // str w11, [x2] + WORD $0xa8c17bfd // ldp x29, x30, [sp], #16 + RET +LBB1_4: + WORD $0x927e7509 // and x9, x8, #0xfffffffc + WORD $0x6f00e401 // movi v1.2d, #0000000000000000 + WORD $0x6f07e7e0 // movi v0.2d, #0xffffffffffffffff + WORD $0x9100200a // add x10, x0, #8 + WORD $0x6f07e7e2 // movi v2.2d, #0xffffffffffffffff + WORD $0xaa0903eb // mov x11, x9 + WORD $0x6f00e403 // movi v3.2d, #0000000000000000 +LBB1_5: + WORD $0x6d7f9544 // ldp d4, d5, [x10, #-8] + WORD $0xf100116b // subs x11, x11, #4 + WORD $0x9100414a // add x10, x10, #16 + WORD $0x2ea46c00 // umin v0.2s, v0.2s, v4.2s + WORD $0x2ea56c42 // umin v2.2s, v2.2s, v5.2s + WORD $0x2ea46421 // umax v1.2s, v1.2s, v4.2s + WORD $0x2ea56463 // umax v3.2s, v3.2s, v5.2s + BNE LBB1_5 + + WORD $0x2ea36421 // umax v1.2s, v1.2s, v3.2s + WORD $0x2ea26c00 // umin v0.2s, v0.2s, v2.2s + WORD $0x0e0c0422 // dup v2.2s, v1.s[1] + WORD $0x0e0c0403 // dup v3.2s, v0.s[1] + WORD $0x2ea26421 // umax v1.2s, v1.2s, v2.2s + WORD $0x2ea36c00 // umin v0.2s, v0.2s, v3.2s + WORD $0xeb08013f // cmp x9, x8 + WORD $0x1e26002a // fmov w10, s1 + WORD $0x1e26000b // fmov w11, s0 + BEQ LBB1_9 +LBB1_7: + WORD $0x8b09080c // add x12, x0, x9, lsl #2 + WORD $0xcb090108 // sub x8, x8, x9 +LBB1_8: + WORD $0xb8404589 // ldr w9, [x12], #4 + WORD $0x6b09017f // cmp w11, w9 + WORD $0x1a89316b // csel w11, w11, w9, lo + WORD $0x6b09015f // cmp w10, w9 + WORD $0x1a89814a // csel w10, w10, w9, hi + WORD $0xf1000508 // subs x8, x8, #1 + BNE LBB1_8 +LBB1_9: + WORD $0xb900006a // str w10, [x3] + WORD $0xb900004b // str w11, [x2] + WORD $0xa8c17bfd // ldp x29, x30, [sp], #16 + RET + +// func _int64_max_min_neon(values unsafe.Pointer, length int, minout, maxout unsafe.Pointer) +TEXT ·_int64_max_min_neon(SB), $0-32 + + MOVD values+0(FP), R0 + MOVD length+8(FP), R1 + MOVD minout+16(FP), R2 + MOVD maxout+24(FP), R3 + + WORD $0xa9bf7bfd // stp x29, x30, [sp, #-16]! + WORD $0x7100043f // cmp w1, #1 + WORD $0x910003fd // mov x29, sp + BLT LBB2_3 + + WORD $0x2a0103e8 // mov w8, w1 + WORD $0xd2f0000b // mov x11, #-9223372036854775808 + WORD $0x71000c3f // cmp w1, #3 + WORD $0x92f0000a // mov x10, #9223372036854775807 + BHI LBB2_4 + + WORD $0xaa1f03e9 // mov x9, xzr + JMP LBB2_7 +LBB2_3: + WORD $0x92f0000a // mov x10, #9223372036854775807 + WORD $0xd2f0000b // mov x11, #-9223372036854775808 + WORD $0xf900006b // str x11, [x3] + WORD $0xf900004a // str x10, [x2] + WORD $0xa8c17bfd // ldp x29, x30, [sp], #16 + RET +LBB2_4: + WORD $0x927e7509 // and x9, x8, #0xfffffffc + WORD $0x4e080d61 // dup v1.2d, x11 + WORD $0x4e080d40 // dup v0.2d, x10 + WORD $0x9100400a // add x10, x0, #16 + WORD $0xaa0903eb // mov x11, x9 + WORD $0x4ea01c02 // mov v2.16b, v0.16b + WORD $0x4ea11c23 // mov v3.16b, v1.16b +LBB2_5: + WORD $0xad7f9544 // ldp q4, q5, [x10, #-16] + WORD $0x4ea31c66 // mov v6.16b, v3.16b + WORD $0x4ea11c27 // mov v7.16b, v1.16b + WORD $0x4ea21c43 // mov v3.16b, v2.16b + WORD $0x4ea01c01 // mov v1.16b, v0.16b + WORD $0x4ee03480 // cmgt v0.2d, v4.2d, v0.2d + WORD $0x4ee234a2 // cmgt v2.2d, v5.2d, v2.2d + WORD $0x6e641c20 // bsl v0.16b, v1.16b, v4.16b + WORD $0x4ee434e1 // cmgt v1.2d, v7.2d, v4.2d + WORD $0x6e651c62 // bsl v2.16b, v3.16b, v5.16b + WORD $0x4ee534c3 // cmgt v3.2d, v6.2d, v5.2d + WORD $0xf100116b // subs x11, x11, #4 + WORD $0x6e641ce1 // bsl v1.16b, v7.16b, v4.16b + WORD $0x6e651cc3 // bsl v3.16b, v6.16b, v5.16b + WORD $0x9100814a // add x10, x10, #32 + BNE LBB2_5 + + WORD $0x4ee33424 // cmgt v4.2d, v1.2d, v3.2d + WORD $0x4ee03445 // cmgt v5.2d, v2.2d, v0.2d + WORD $0x6e631c24 // bsl v4.16b, v1.16b, v3.16b + WORD $0x6e621c05 // bsl v5.16b, v0.16b, v2.16b + WORD $0x4e180480 // dup v0.2d, v4.d[1] + WORD $0x4e1804a1 // dup v1.2d, v5.d[1] + WORD $0x4ee03482 // cmgt v2.2d, v4.2d, v0.2d + WORD $0x4ee53423 // cmgt v3.2d, v1.2d, v5.2d + WORD $0x6e601c82 // bsl v2.16b, v4.16b, v0.16b + WORD $0x6e611ca3 // bsl v3.16b, v5.16b, v1.16b + WORD $0xeb08013f // cmp x9, x8 + WORD $0x9e66004b // fmov x11, d2 + WORD $0x9e66006a // fmov x10, d3 + BEQ LBB2_9 +LBB2_7: + WORD $0x8b090c0c // add x12, x0, x9, lsl #3 + WORD $0xcb090108 // sub x8, x8, x9 +LBB2_8: + WORD $0xf8408589 // ldr x9, [x12], #8 + WORD $0xeb09015f // cmp x10, x9 + WORD $0x9a89b14a // csel x10, x10, x9, lt + WORD $0xeb09017f // cmp x11, x9 + WORD $0x9a89c16b // csel x11, x11, x9, gt + WORD $0xf1000508 // subs x8, x8, #1 + BNE LBB2_8 +LBB2_9: + WORD $0xf900006b // str x11, [x3] + WORD $0xf900004a // str x10, [x2] + WORD $0xa8c17bfd // ldp x29, x30, [sp], #16 + RET + + +// func _uint64_max_min_neon(values unsafe.Pointer, length int, minout, maxout unsafe.Pointer) +TEXT ·_uint64_max_min_neon(SB), $0-32 + + MOVD values+0(FP), R0 + MOVD length+8(FP), R1 + MOVD minout+16(FP), R2 + MOVD maxout+24(FP), R3 + + WORD $0xa9bf7bfd // stp x29, x30, [sp, #-16]! + WORD $0x7100043f // cmp w1, #1 + WORD $0x910003fd // mov x29, sp + BLT LBB3_3 + + WORD $0x71000c3f // cmp w1, #3 + WORD $0x2a0103e8 // mov w8, w1 + BHI LBB3_4 + + WORD $0xaa1f03e9 // mov x9, xzr + WORD $0xaa1f03ea // mov x10, xzr + WORD $0x9280000b // mov x11, #-1 + JMP LBB3_7 +LBB3_3: + WORD $0xaa1f03ea // mov x10, xzr + WORD $0x9280000b // mov x11, #-1 + WORD $0xf900006a // str x10, [x3] + WORD $0xf900004b // str x11, [x2] + WORD $0xa8c17bfd // ldp x29, x30, [sp], #16 + RET +LBB3_4: + WORD $0x927e7509 // and x9, x8, #0xfffffffc + WORD $0x9100400a // add x10, x0, #16 + WORD $0x6f00e401 // movi v1.2d, #0000000000000000 + WORD $0x6f07e7e0 // movi v0.2d, #0xffffffffffffffff + WORD $0x6f07e7e2 // movi v2.2d, #0xffffffffffffffff + WORD $0xaa0903eb // mov x11, x9 + WORD $0x6f00e403 // movi v3.2d, #0000000000000000 +LBB3_5: + WORD $0xad7f9544 // ldp q4, q5, [x10, #-16] + WORD $0x4ea31c66 // mov v6.16b, v3.16b + WORD $0x4ea11c27 // mov v7.16b, v1.16b + WORD $0x4ea21c43 // mov v3.16b, v2.16b + WORD $0x4ea01c01 // mov v1.16b, v0.16b + WORD $0x6ee03480 // cmhi v0.2d, v4.2d, v0.2d + WORD $0x6ee234a2 // cmhi v2.2d, v5.2d, v2.2d + WORD $0x6e641c20 // bsl v0.16b, v1.16b, v4.16b + WORD $0x6ee434e1 // cmhi v1.2d, v7.2d, v4.2d + WORD $0x6e651c62 // bsl v2.16b, v3.16b, v5.16b + WORD $0x6ee534c3 // cmhi v3.2d, v6.2d, v5.2d + WORD $0xf100116b // subs x11, x11, #4 + WORD $0x6e641ce1 // bsl v1.16b, v7.16b, v4.16b + WORD $0x6e651cc3 // bsl v3.16b, v6.16b, v5.16b + WORD $0x9100814a // add x10, x10, #32 + BNE LBB3_5 + + WORD $0x6ee33424 // cmhi v4.2d, v1.2d, v3.2d + WORD $0x6ee03445 // cmhi v5.2d, v2.2d, v0.2d + WORD $0x6e631c24 // bsl v4.16b, v1.16b, v3.16b + WORD $0x6e621c05 // bsl v5.16b, v0.16b, v2.16b + WORD $0x4e180480 // dup v0.2d, v4.d[1] + WORD $0x4e1804a1 // dup v1.2d, v5.d[1] + WORD $0x6ee03482 // cmhi v2.2d, v4.2d, v0.2d + WORD $0x6ee53423 // cmhi v3.2d, v1.2d, v5.2d + WORD $0x6e601c82 // bsl v2.16b, v4.16b, v0.16b + WORD $0x6e611ca3 // bsl v3.16b, v5.16b, v1.16b + WORD $0xeb08013f // cmp x9, x8 + WORD $0x9e66004a // fmov x10, d2 + WORD $0x9e66006b // fmov x11, d3 + BEQ LBB3_9 +LBB3_7: + WORD $0x8b090c0c // add x12, x0, x9, lsl #3 + WORD $0xcb090108 // sub x8, x8, x9 +LBB3_8: + WORD $0xf8408589 // ldr x9, [x12], #8 + WORD $0xeb09017f // cmp x11, x9 + WORD $0x9a89316b // csel x11, x11, x9, lo + WORD $0xeb09015f // cmp x10, x9 + WORD $0x9a89814a // csel x10, x10, x9, hi + WORD $0xf1000508 // subs x8, x8, #1 + BNE LBB3_8 +LBB3_9: + WORD $0xf900006a // str x10, [x3] + WORD $0xf900004b // str x11, [x2] + WORD $0xa8c17bfd // ldp x29, x30, [sp], #16 + RET + diff --git a/vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_noasm.go b/vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_noasm.go new file mode 100644 index 000000000..19c24b590 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_noasm.go @@ -0,0 +1,31 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build noasm + +package utils + +// if building with the 'noasm' tag, then point to the pure go implementations +func init() { + minmaxFuncs.i8 = int8MinMax + minmaxFuncs.ui8 = uint8MinMax + minmaxFuncs.i16 = int16MinMax + minmaxFuncs.ui16 = uint16MinMax + minmaxFuncs.i32 = int32MinMax + minmaxFuncs.ui32 = uint32MinMax + minmaxFuncs.i64 = int64MinMax + minmaxFuncs.ui64 = uint64MinMax +} diff --git a/vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_ppc64le.go b/vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_ppc64le.go new file mode 100644 index 000000000..ffd2db006 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_ppc64le.go @@ -0,0 +1,30 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !noasm + +package utils + +func init() { + minmaxFuncs.i8 = int8MinMax + minmaxFuncs.ui8 = uint8MinMax + minmaxFuncs.i16 = int16MinMax + minmaxFuncs.ui16 = uint16MinMax + minmaxFuncs.i32 = int32MinMax + minmaxFuncs.ui32 = uint32MinMax + minmaxFuncs.i64 = int64MinMax + minmaxFuncs.ui64 = uint64MinMax +} diff --git a/vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_s390x.go b/vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_s390x.go new file mode 100644 index 000000000..ffd2db006 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_s390x.go @@ -0,0 +1,30 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !noasm + +package utils + +func init() { + minmaxFuncs.i8 = int8MinMax + minmaxFuncs.ui8 = uint8MinMax + minmaxFuncs.i16 = int16MinMax + minmaxFuncs.ui16 = uint16MinMax + minmaxFuncs.i32 = int32MinMax + minmaxFuncs.ui32 = uint32MinMax + minmaxFuncs.i64 = int64MinMax + minmaxFuncs.ui64 = uint64MinMax +} diff --git a/vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_sse4_amd64.go b/vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_sse4_amd64.go new file mode 100644 index 000000000..1e12a8d17 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_sse4_amd64.go @@ -0,0 +1,88 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !noasm + +package utils + +import "unsafe" + +// This file contains convenience functions for utilizing SSE4 intrinsics to quickly +// and efficiently get the min and max from an integral slice. + +//go:noescape +func _int8_max_min_sse4(values unsafe.Pointer, length int, minout, maxout unsafe.Pointer) + +func int8MaxMinSSE4(values []int8) (min, max int8) { + _int8_max_min_sse4(unsafe.Pointer(&values[0]), len(values), unsafe.Pointer(&min), unsafe.Pointer(&max)) + return +} + +//go:noescape +func _uint8_max_min_sse4(values unsafe.Pointer, length int, minout, maxout unsafe.Pointer) + +func uint8MaxMinSSE4(values []uint8) (min, max uint8) { + _uint8_max_min_sse4(unsafe.Pointer(&values[0]), len(values), unsafe.Pointer(&min), unsafe.Pointer(&max)) + return +} + +//go:noescape +func _int16_max_min_sse4(values unsafe.Pointer, length int, minout, maxout unsafe.Pointer) + +func int16MaxMinSSE4(values []int16) (min, max int16) { + _int16_max_min_sse4(unsafe.Pointer(&values[0]), len(values), unsafe.Pointer(&min), unsafe.Pointer(&max)) + return +} + +//go:noescape +func _uint16_max_min_sse4(values unsafe.Pointer, length int, minout, maxout unsafe.Pointer) + +func uint16MaxMinSSE4(values []uint16) (min, max uint16) { + _uint16_max_min_sse4(unsafe.Pointer(&values[0]), len(values), unsafe.Pointer(&min), unsafe.Pointer(&max)) + return +} + +//go:noescape +func _int32_max_min_sse4(values unsafe.Pointer, length int, minout, maxout unsafe.Pointer) + +func int32MaxMinSSE4(values []int32) (min, max int32) { + _int32_max_min_sse4(unsafe.Pointer(&values[0]), len(values), unsafe.Pointer(&min), unsafe.Pointer(&max)) + return +} + +//go:noescape +func _uint32_max_min_sse4(values unsafe.Pointer, length int, minout, maxout unsafe.Pointer) + +func uint32MaxMinSSE4(values []uint32) (min, max uint32) { + _uint32_max_min_sse4(unsafe.Pointer(&values[0]), len(values), unsafe.Pointer(&min), unsafe.Pointer(&max)) + return +} + +//go:noescape +func _int64_max_min_sse4(values unsafe.Pointer, length int, minout, maxout unsafe.Pointer) + +func int64MaxMinSSE4(values []int64) (min, max int64) { + _int64_max_min_sse4(unsafe.Pointer(&values[0]), len(values), unsafe.Pointer(&min), unsafe.Pointer(&max)) + return +} + +//go:noescape +func _uint64_max_min_sse4(values unsafe.Pointer, length int, minout, maxout unsafe.Pointer) + +func uint64MaxMinSSE4(values []uint64) (min, max uint64) { + _uint64_max_min_sse4(unsafe.Pointer(&values[0]), len(values), unsafe.Pointer(&min), unsafe.Pointer(&max)) + return +} diff --git a/vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_sse4_amd64.s b/vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_sse4_amd64.s new file mode 100644 index 000000000..8f1eccf60 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/utils/min_max_sse4_amd64.s @@ -0,0 +1,1044 @@ +//+build !noasm !appengine +// AUTO-GENERATED BY C2GOASM -- DO NOT EDIT + +DATA LCDATA1<>+0x000(SB)/8, $0x8080808080808080 +DATA LCDATA1<>+0x008(SB)/8, $0x8080808080808080 +DATA LCDATA1<>+0x010(SB)/8, $0x7f7f7f7f7f7f7f7f +DATA LCDATA1<>+0x018(SB)/8, $0x7f7f7f7f7f7f7f7f +GLOBL LCDATA1<>(SB), 8, $32 + +TEXT ·_int8_max_min_sse4(SB), $0-32 + + MOVQ values+0(FP), DI + MOVQ length+8(FP), SI + MOVQ minout+16(FP), DX + MOVQ maxout+24(FP), CX + LEAQ LCDATA1<>(SB), BP + + WORD $0xf685 // test esi, esi + JLE LBB0_1 + WORD $0x8941; BYTE $0xf1 // mov r9d, esi + WORD $0xfe83; BYTE $0x1f // cmp esi, 31 + JA LBB0_4 + WORD $0xb041; BYTE $0x80 // mov r8b, -128 + WORD $0xb640; BYTE $0x7f // mov sil, 127 + WORD $0x3145; BYTE $0xdb // xor r11d, r11d + JMP LBB0_11 + +LBB0_1: + WORD $0xb640; BYTE $0x7f // mov sil, 127 + WORD $0xb041; BYTE $0x80 // mov r8b, -128 + JMP LBB0_12 + +LBB0_4: + WORD $0x8945; BYTE $0xcb // mov r11d, r9d + LONG $0xe0e38341 // and r11d, -32 + LONG $0xe0438d49 // lea rax, [r11 - 32] + WORD $0x8949; BYTE $0xc0 // mov r8, rax + LONG $0x05e8c149 // shr r8, 5 + LONG $0x01c08349 // add r8, 1 + WORD $0x8548; BYTE $0xc0 // test rax, rax + JE LBB0_5 + WORD $0x894d; BYTE $0xc2 // mov r10, r8 + LONG $0xfee28349 // and r10, -2 + WORD $0xf749; BYTE $0xda // neg r10 + LONG $0x4d6f0f66; BYTE $0x00 // movdqa xmm1, oword 0[rbp] /* [rip + .LCPI0_0] */ + LONG $0x456f0f66; BYTE $0x10 // movdqa xmm0, oword 16[rbp] /* [rip + .LCPI0_1] */ + WORD $0xc031 // xor eax, eax + LONG $0xd06f0f66 // movdqa xmm2, xmm0 + LONG $0xd96f0f66 // movdqa xmm3, xmm1 + +LBB0_7: + LONG $0x246f0ff3; BYTE $0x07 // movdqu xmm4, oword [rdi + rax] + LONG $0x6c6f0ff3; WORD $0x1007 // movdqu xmm5, oword [rdi + rax + 16] + LONG $0x746f0ff3; WORD $0x2007 // movdqu xmm6, oword [rdi + rax + 32] + LONG $0x7c6f0ff3; WORD $0x3007 // movdqu xmm7, oword [rdi + rax + 48] + LONG $0x38380f66; BYTE $0xc4 // pminsb xmm0, xmm4 + LONG $0x38380f66; BYTE $0xd5 // pminsb xmm2, xmm5 + LONG $0x3c380f66; BYTE $0xcc // pmaxsb xmm1, xmm4 + LONG $0x3c380f66; BYTE $0xdd // pmaxsb xmm3, xmm5 + LONG $0x38380f66; BYTE $0xc6 // pminsb xmm0, xmm6 + LONG $0x38380f66; BYTE $0xd7 // pminsb xmm2, xmm7 + LONG $0x3c380f66; BYTE $0xce // pmaxsb xmm1, xmm6 + LONG $0x3c380f66; BYTE $0xdf // pmaxsb xmm3, xmm7 + LONG $0x40c08348 // add rax, 64 + LONG $0x02c28349 // add r10, 2 + JNE LBB0_7 + LONG $0x01c0f641 // test r8b, 1 + JE LBB0_10 + +LBB0_9: + LONG $0x246f0ff3; BYTE $0x07 // movdqu xmm4, oword [rdi + rax] + LONG $0x6c6f0ff3; WORD $0x1007 // movdqu xmm5, oword [rdi + rax + 16] + LONG $0x3c380f66; BYTE $0xdd // pmaxsb xmm3, xmm5 + LONG $0x3c380f66; BYTE $0xcc // pmaxsb xmm1, xmm4 + LONG $0x38380f66; BYTE $0xd5 // pminsb xmm2, xmm5 + LONG $0x38380f66; BYTE $0xc4 // pminsb xmm0, xmm4 + +LBB0_10: + LONG $0x38380f66; BYTE $0xc2 // pminsb xmm0, xmm2 + LONG $0x3c380f66; BYTE $0xcb // pmaxsb xmm1, xmm3 + LONG $0x4def0f66; BYTE $0x10 // pxor xmm1, oword 16[rbp] /* [rip + .LCPI0_1] */ + LONG $0xd16f0f66 // movdqa xmm2, xmm1 + LONG $0xd2710f66; BYTE $0x08 // psrlw xmm2, 8 + LONG $0xd1da0f66 // pminub xmm2, xmm1 + LONG $0x41380f66; BYTE $0xca // phminposuw xmm1, xmm2 + LONG $0x7e0f4166; BYTE $0xc8 // movd r8d, xmm1 + LONG $0x7ff08041 // xor r8b, 127 + LONG $0x45ef0f66; BYTE $0x00 // pxor xmm0, oword 0[rbp] /* [rip + .LCPI0_0] */ + LONG $0xc86f0f66 // movdqa xmm1, xmm0 + LONG $0xd1710f66; BYTE $0x08 // psrlw xmm1, 8 + LONG $0xc8da0f66 // pminub xmm1, xmm0 + LONG $0x41380f66; BYTE $0xc1 // phminposuw xmm0, xmm1 + LONG $0xc67e0f66 // movd esi, xmm0 + LONG $0x80f68040 // xor sil, -128 + WORD $0x394d; BYTE $0xcb // cmp r11, r9 + JE LBB0_12 + +LBB0_11: + LONG $0x04b60f42; BYTE $0x1f // movzx eax, byte [rdi + r11] + WORD $0x3840; BYTE $0xc6 // cmp sil, al + LONG $0xf6b60f40 // movzx esi, sil + WORD $0x4f0f; BYTE $0xf0 // cmovg esi, eax + WORD $0x3841; BYTE $0xc0 // cmp r8b, al + LONG $0xc0b60f45 // movzx r8d, r8b + LONG $0xc04c0f44 // cmovl r8d, eax + LONG $0x01c38349 // add r11, 1 + WORD $0x394d; BYTE $0xd9 // cmp r9, r11 + JNE LBB0_11 + +LBB0_12: + WORD $0x8844; BYTE $0x01 // mov byte [rcx], r8b + WORD $0x8840; BYTE $0x32 // mov byte [rdx], sil + RET + +LBB0_5: + LONG $0x4d6f0f66; BYTE $0x00 // movdqa xmm1, oword 0[rbp] /* [rip + .LCPI0_0] */ + LONG $0x456f0f66; BYTE $0x10 // movdqa xmm0, oword 16[rbp] /* [rip + .LCPI0_1] */ + WORD $0xc031 // xor eax, eax + LONG $0xd06f0f66 // movdqa xmm2, xmm0 + LONG $0xd96f0f66 // movdqa xmm3, xmm1 + LONG $0x01c0f641 // test r8b, 1 + JNE LBB0_9 + JMP LBB0_10 + +TEXT ·_uint8_max_min_sse4(SB), $0-32 + + MOVQ values+0(FP), DI + MOVQ length+8(FP), SI + MOVQ minout+16(FP), DX + MOVQ maxout+24(FP), CX + + WORD $0xf685 // test esi, esi + JLE LBB1_1 + WORD $0x8941; BYTE $0xf1 // mov r9d, esi + WORD $0xfe83; BYTE $0x1f // cmp esi, 31 + JA LBB1_4 + WORD $0xb640; BYTE $0xff // mov sil, -1 + WORD $0x3145; BYTE $0xdb // xor r11d, r11d + WORD $0xc031 // xor eax, eax + JMP LBB1_11 + +LBB1_1: + WORD $0xb640; BYTE $0xff // mov sil, -1 + WORD $0xc031 // xor eax, eax + JMP LBB1_12 + +LBB1_4: + WORD $0x8945; BYTE $0xcb // mov r11d, r9d + LONG $0xe0e38341 // and r11d, -32 + LONG $0xe0438d49 // lea rax, [r11 - 32] + WORD $0x8949; BYTE $0xc0 // mov r8, rax + LONG $0x05e8c149 // shr r8, 5 + LONG $0x01c08349 // add r8, 1 + WORD $0x8548; BYTE $0xc0 // test rax, rax + JE LBB1_5 + WORD $0x894d; BYTE $0xc2 // mov r10, r8 + LONG $0xfee28349 // and r10, -2 + WORD $0xf749; BYTE $0xda // neg r10 + LONG $0xc9ef0f66 // pxor xmm1, xmm1 + LONG $0xc0760f66 // pcmpeqd xmm0, xmm0 + WORD $0xc031 // xor eax, eax + LONG $0xd2760f66 // pcmpeqd xmm2, xmm2 + LONG $0xdbef0f66 // pxor xmm3, xmm3 + +LBB1_7: + LONG $0x246f0ff3; BYTE $0x07 // movdqu xmm4, oword [rdi + rax] + LONG $0x6c6f0ff3; WORD $0x1007 // movdqu xmm5, oword [rdi + rax + 16] + LONG $0x746f0ff3; WORD $0x2007 // movdqu xmm6, oword [rdi + rax + 32] + LONG $0x7c6f0ff3; WORD $0x3007 // movdqu xmm7, oword [rdi + rax + 48] + LONG $0xc4da0f66 // pminub xmm0, xmm4 + LONG $0xd5da0f66 // pminub xmm2, xmm5 + LONG $0xccde0f66 // pmaxub xmm1, xmm4 + LONG $0xddde0f66 // pmaxub xmm3, xmm5 + LONG $0xc6da0f66 // pminub xmm0, xmm6 + LONG $0xd7da0f66 // pminub xmm2, xmm7 + LONG $0xcede0f66 // pmaxub xmm1, xmm6 + LONG $0xdfde0f66 // pmaxub xmm3, xmm7 + LONG $0x40c08348 // add rax, 64 + LONG $0x02c28349 // add r10, 2 + JNE LBB1_7 + LONG $0x01c0f641 // test r8b, 1 + JE LBB1_10 + +LBB1_9: + LONG $0x246f0ff3; BYTE $0x07 // movdqu xmm4, oword [rdi + rax] + LONG $0x6c6f0ff3; WORD $0x1007 // movdqu xmm5, oword [rdi + rax + 16] + LONG $0xddde0f66 // pmaxub xmm3, xmm5 + LONG $0xccde0f66 // pmaxub xmm1, xmm4 + LONG $0xd5da0f66 // pminub xmm2, xmm5 + LONG $0xc4da0f66 // pminub xmm0, xmm4 + +LBB1_10: + LONG $0xc2da0f66 // pminub xmm0, xmm2 + LONG $0xcbde0f66 // pmaxub xmm1, xmm3 + LONG $0xd2760f66 // pcmpeqd xmm2, xmm2 + LONG $0xd1ef0f66 // pxor xmm2, xmm1 + LONG $0xca6f0f66 // movdqa xmm1, xmm2 + LONG $0xd1710f66; BYTE $0x08 // psrlw xmm1, 8 + LONG $0xcada0f66 // pminub xmm1, xmm2 + LONG $0x41380f66; BYTE $0xc9 // phminposuw xmm1, xmm1 + LONG $0xc87e0f66 // movd eax, xmm1 + WORD $0xd0f6 // not al + LONG $0xc86f0f66 // movdqa xmm1, xmm0 + LONG $0xd1710f66; BYTE $0x08 // psrlw xmm1, 8 + LONG $0xc8da0f66 // pminub xmm1, xmm0 + LONG $0x41380f66; BYTE $0xc1 // phminposuw xmm0, xmm1 + LONG $0xc67e0f66 // movd esi, xmm0 + WORD $0x394d; BYTE $0xcb // cmp r11, r9 + JE LBB1_12 + +LBB1_11: + LONG $0x04b60f46; BYTE $0x1f // movzx r8d, byte [rdi + r11] + WORD $0x3844; BYTE $0xc6 // cmp sil, r8b + LONG $0xf6b60f40 // movzx esi, sil + LONG $0xf0430f41 // cmovae esi, r8d + WORD $0x3844; BYTE $0xc0 // cmp al, r8b + WORD $0xb60f; BYTE $0xc0 // movzx eax, al + LONG $0xc0460f41 // cmovbe eax, r8d + LONG $0x01c38349 // add r11, 1 + WORD $0x394d; BYTE $0xd9 // cmp r9, r11 + JNE LBB1_11 + +LBB1_12: + WORD $0x0188 // mov byte [rcx], al + WORD $0x8840; BYTE $0x32 // mov byte [rdx], sil + RET + +LBB1_5: + LONG $0xc9ef0f66 // pxor xmm1, xmm1 + LONG $0xc0760f66 // pcmpeqd xmm0, xmm0 + WORD $0xc031 // xor eax, eax + LONG $0xd2760f66 // pcmpeqd xmm2, xmm2 + LONG $0xdbef0f66 // pxor xmm3, xmm3 + LONG $0x01c0f641 // test r8b, 1 + JNE LBB1_9 + JMP LBB1_10 + +DATA LCDATA2<>+0x000(SB)/8, $0x8000800080008000 +DATA LCDATA2<>+0x008(SB)/8, $0x8000800080008000 +DATA LCDATA2<>+0x010(SB)/8, $0x7fff7fff7fff7fff +DATA LCDATA2<>+0x018(SB)/8, $0x7fff7fff7fff7fff +GLOBL LCDATA2<>(SB), 8, $32 + +TEXT ·_int16_max_min_sse4(SB), $0-32 + + MOVQ values+0(FP), DI + MOVQ length+8(FP), SI + MOVQ minout+16(FP), DX + MOVQ maxout+24(FP), CX + LEAQ LCDATA2<>(SB), BP + + WORD $0xf685 // test esi, esi + JLE LBB2_1 + WORD $0x8941; BYTE $0xf1 // mov r9d, esi + WORD $0xfe83; BYTE $0x0f // cmp esi, 15 + JA LBB2_4 + LONG $0x00b84166; BYTE $0x80 // mov r8w, -32768 + LONG $0x7fffbe66 // mov si, 32767 + WORD $0x3145; BYTE $0xdb // xor r11d, r11d + JMP LBB2_11 + +LBB2_1: + LONG $0x7fffbe66 // mov si, 32767 + LONG $0x00b84166; BYTE $0x80 // mov r8w, -32768 + JMP LBB2_12 + +LBB2_4: + WORD $0x8945; BYTE $0xcb // mov r11d, r9d + LONG $0xf0e38341 // and r11d, -16 + LONG $0xf0438d49 // lea rax, [r11 - 16] + WORD $0x8949; BYTE $0xc0 // mov r8, rax + LONG $0x04e8c149 // shr r8, 4 + LONG $0x01c08349 // add r8, 1 + WORD $0x8548; BYTE $0xc0 // test rax, rax + JE LBB2_5 + WORD $0x894d; BYTE $0xc2 // mov r10, r8 + LONG $0xfee28349 // and r10, -2 + WORD $0xf749; BYTE $0xda // neg r10 + LONG $0x4d6f0f66; BYTE $0x00 // movdqa xmm1, oword 0[rbp] /* [rip + .LCPI2_0] */ + LONG $0x456f0f66; BYTE $0x10 // movdqa xmm0, oword 16[rbp] /* [rip + .LCPI2_1] */ + WORD $0xc031 // xor eax, eax + LONG $0xd06f0f66 // movdqa xmm2, xmm0 + LONG $0xd96f0f66 // movdqa xmm3, xmm1 + +LBB2_7: + LONG $0x246f0ff3; BYTE $0x47 // movdqu xmm4, oword [rdi + 2*rax] + LONG $0x6c6f0ff3; WORD $0x1047 // movdqu xmm5, oword [rdi + 2*rax + 16] + LONG $0x746f0ff3; WORD $0x2047 // movdqu xmm6, oword [rdi + 2*rax + 32] + LONG $0x7c6f0ff3; WORD $0x3047 // movdqu xmm7, oword [rdi + 2*rax + 48] + LONG $0xc4ea0f66 // pminsw xmm0, xmm4 + LONG $0xd5ea0f66 // pminsw xmm2, xmm5 + LONG $0xccee0f66 // pmaxsw xmm1, xmm4 + LONG $0xddee0f66 // pmaxsw xmm3, xmm5 + LONG $0xc6ea0f66 // pminsw xmm0, xmm6 + LONG $0xd7ea0f66 // pminsw xmm2, xmm7 + LONG $0xceee0f66 // pmaxsw xmm1, xmm6 + LONG $0xdfee0f66 // pmaxsw xmm3, xmm7 + LONG $0x20c08348 // add rax, 32 + LONG $0x02c28349 // add r10, 2 + JNE LBB2_7 + LONG $0x01c0f641 // test r8b, 1 + JE LBB2_10 + +LBB2_9: + LONG $0x246f0ff3; BYTE $0x47 // movdqu xmm4, oword [rdi + 2*rax] + LONG $0x6c6f0ff3; WORD $0x1047 // movdqu xmm5, oword [rdi + 2*rax + 16] + LONG $0xddee0f66 // pmaxsw xmm3, xmm5 + LONG $0xccee0f66 // pmaxsw xmm1, xmm4 + LONG $0xd5ea0f66 // pminsw xmm2, xmm5 + LONG $0xc4ea0f66 // pminsw xmm0, xmm4 + +LBB2_10: + LONG $0xc2ea0f66 // pminsw xmm0, xmm2 + LONG $0xcbee0f66 // pmaxsw xmm1, xmm3 + LONG $0x4def0f66; BYTE $0x10 // pxor xmm1, oword 16[rbp] /* [rip + .LCPI2_1] */ + LONG $0x41380f66; BYTE $0xc9 // phminposuw xmm1, xmm1 + LONG $0x7e0f4166; BYTE $0xc8 // movd r8d, xmm1 + LONG $0xfff08141; WORD $0x007f; BYTE $0x00 // xor r8d, 32767 + LONG $0x45ef0f66; BYTE $0x00 // pxor xmm0, oword 0[rbp] /* [rip + .LCPI2_0] */ + LONG $0x41380f66; BYTE $0xc0 // phminposuw xmm0, xmm0 + LONG $0xc67e0f66 // movd esi, xmm0 + LONG $0x8000f681; WORD $0x0000 // xor esi, 32768 + WORD $0x394d; BYTE $0xcb // cmp r11, r9 + JE LBB2_12 + +LBB2_11: + LONG $0x04b70f42; BYTE $0x5f // movzx eax, word [rdi + 2*r11] + WORD $0x3966; BYTE $0xc6 // cmp si, ax + WORD $0x4f0f; BYTE $0xf0 // cmovg esi, eax + LONG $0xc0394166 // cmp r8w, ax + LONG $0xc04c0f44 // cmovl r8d, eax + LONG $0x01c38349 // add r11, 1 + WORD $0x394d; BYTE $0xd9 // cmp r9, r11 + JNE LBB2_11 + +LBB2_12: + LONG $0x01894466 // mov word [rcx], r8w + WORD $0x8966; BYTE $0x32 // mov word [rdx], si + RET + +LBB2_5: + LONG $0x4d6f0f66; BYTE $0x00 // movdqa xmm1, oword 0[rbp] /* [rip + .LCPI2_0] */ + LONG $0x456f0f66; BYTE $0x10 // movdqa xmm0, oword 16[rbp] /* [rip + .LCPI2_1] */ + WORD $0xc031 // xor eax, eax + LONG $0xd06f0f66 // movdqa xmm2, xmm0 + LONG $0xd96f0f66 // movdqa xmm3, xmm1 + LONG $0x01c0f641 // test r8b, 1 + JNE LBB2_9 + JMP LBB2_10 + +TEXT ·_uint16_max_min_sse4(SB), $0-32 + + MOVQ values+0(FP), DI + MOVQ length+8(FP), SI + MOVQ minout+16(FP), DX + MOVQ maxout+24(FP), CX + + WORD $0xf685 // test esi, esi + JLE LBB3_1 + WORD $0x8941; BYTE $0xf1 // mov r9d, esi + WORD $0xfe83; BYTE $0x0f // cmp esi, 15 + JA LBB3_4 + LONG $0xffb84166; BYTE $0xff // mov r8w, -1 + WORD $0x3145; BYTE $0xdb // xor r11d, r11d + WORD $0xf631 // xor esi, esi + JMP LBB3_11 + +LBB3_1: + LONG $0xffb84166; BYTE $0xff // mov r8w, -1 + WORD $0xf631 // xor esi, esi + JMP LBB3_12 + +LBB3_4: + WORD $0x8945; BYTE $0xcb // mov r11d, r9d + LONG $0xf0e38341 // and r11d, -16 + LONG $0xf0438d49 // lea rax, [r11 - 16] + WORD $0x8949; BYTE $0xc0 // mov r8, rax + LONG $0x04e8c149 // shr r8, 4 + LONG $0x01c08349 // add r8, 1 + WORD $0x8548; BYTE $0xc0 // test rax, rax + JE LBB3_5 + WORD $0x894d; BYTE $0xc2 // mov r10, r8 + LONG $0xfee28349 // and r10, -2 + WORD $0xf749; BYTE $0xda // neg r10 + LONG $0xc9ef0f66 // pxor xmm1, xmm1 + LONG $0xc0760f66 // pcmpeqd xmm0, xmm0 + WORD $0xc031 // xor eax, eax + LONG $0xd2760f66 // pcmpeqd xmm2, xmm2 + LONG $0xdbef0f66 // pxor xmm3, xmm3 + +LBB3_7: + LONG $0x246f0ff3; BYTE $0x47 // movdqu xmm4, oword [rdi + 2*rax] + LONG $0x6c6f0ff3; WORD $0x1047 // movdqu xmm5, oword [rdi + 2*rax + 16] + LONG $0x746f0ff3; WORD $0x2047 // movdqu xmm6, oword [rdi + 2*rax + 32] + LONG $0x7c6f0ff3; WORD $0x3047 // movdqu xmm7, oword [rdi + 2*rax + 48] + LONG $0x3a380f66; BYTE $0xc4 // pminuw xmm0, xmm4 + LONG $0x3a380f66; BYTE $0xd5 // pminuw xmm2, xmm5 + LONG $0x3e380f66; BYTE $0xcc // pmaxuw xmm1, xmm4 + LONG $0x3e380f66; BYTE $0xdd // pmaxuw xmm3, xmm5 + LONG $0x3a380f66; BYTE $0xc6 // pminuw xmm0, xmm6 + LONG $0x3a380f66; BYTE $0xd7 // pminuw xmm2, xmm7 + LONG $0x3e380f66; BYTE $0xce // pmaxuw xmm1, xmm6 + LONG $0x3e380f66; BYTE $0xdf // pmaxuw xmm3, xmm7 + LONG $0x20c08348 // add rax, 32 + LONG $0x02c28349 // add r10, 2 + JNE LBB3_7 + LONG $0x01c0f641 // test r8b, 1 + JE LBB3_10 + +LBB3_9: + LONG $0x246f0ff3; BYTE $0x47 // movdqu xmm4, oword [rdi + 2*rax] + LONG $0x6c6f0ff3; WORD $0x1047 // movdqu xmm5, oword [rdi + 2*rax + 16] + LONG $0x3e380f66; BYTE $0xdd // pmaxuw xmm3, xmm5 + LONG $0x3e380f66; BYTE $0xcc // pmaxuw xmm1, xmm4 + LONG $0x3a380f66; BYTE $0xd5 // pminuw xmm2, xmm5 + LONG $0x3a380f66; BYTE $0xc4 // pminuw xmm0, xmm4 + +LBB3_10: + LONG $0x3a380f66; BYTE $0xc2 // pminuw xmm0, xmm2 + LONG $0x3e380f66; BYTE $0xcb // pmaxuw xmm1, xmm3 + LONG $0xd2760f66 // pcmpeqd xmm2, xmm2 + LONG $0xd1ef0f66 // pxor xmm2, xmm1 + LONG $0x41380f66; BYTE $0xca // phminposuw xmm1, xmm2 + LONG $0xce7e0f66 // movd esi, xmm1 + WORD $0xd6f7 // not esi + LONG $0x41380f66; BYTE $0xc0 // phminposuw xmm0, xmm0 + LONG $0x7e0f4166; BYTE $0xc0 // movd r8d, xmm0 + WORD $0x394d; BYTE $0xcb // cmp r11, r9 + JE LBB3_12 + +LBB3_11: + LONG $0x04b70f42; BYTE $0x5f // movzx eax, word [rdi + 2*r11] + LONG $0xc0394166 // cmp r8w, ax + LONG $0xc0430f44 // cmovae r8d, eax + WORD $0x3966; BYTE $0xc6 // cmp si, ax + WORD $0x460f; BYTE $0xf0 // cmovbe esi, eax + LONG $0x01c38349 // add r11, 1 + WORD $0x394d; BYTE $0xd9 // cmp r9, r11 + JNE LBB3_11 + +LBB3_12: + WORD $0x8966; BYTE $0x31 // mov word [rcx], si + LONG $0x02894466 // mov word [rdx], r8w + RET + +LBB3_5: + LONG $0xc9ef0f66 // pxor xmm1, xmm1 + LONG $0xc0760f66 // pcmpeqd xmm0, xmm0 + WORD $0xc031 // xor eax, eax + LONG $0xd2760f66 // pcmpeqd xmm2, xmm2 + LONG $0xdbef0f66 // pxor xmm3, xmm3 + LONG $0x01c0f641 // test r8b, 1 + JNE LBB3_9 + JMP LBB3_10 + +DATA LCDATA3<>+0x000(SB)/8, $0x8000000080000000 +DATA LCDATA3<>+0x008(SB)/8, $0x8000000080000000 +DATA LCDATA3<>+0x010(SB)/8, $0x7fffffff7fffffff +DATA LCDATA3<>+0x018(SB)/8, $0x7fffffff7fffffff +GLOBL LCDATA3<>(SB), 8, $32 + +TEXT ·_int32_max_min_sse4(SB), $0-32 + + MOVQ values+0(FP), DI + MOVQ length+8(FP), SI + MOVQ minout+16(FP), DX + MOVQ maxout+24(FP), CX + LEAQ LCDATA3<>(SB), BP + + WORD $0xf685 // test esi, esi + JLE LBB4_1 + WORD $0x8941; BYTE $0xf1 // mov r9d, esi + WORD $0xfe83; BYTE $0x07 // cmp esi, 7 + JA LBB4_6 + LONG $0x000000b8; BYTE $0x80 // mov eax, -2147483648 + LONG $0xffffb841; WORD $0x7fff // mov r8d, 2147483647 + WORD $0x3145; BYTE $0xdb // xor r11d, r11d + JMP LBB4_4 + +LBB4_1: + LONG $0xffffb841; WORD $0x7fff // mov r8d, 2147483647 + LONG $0x000000b8; BYTE $0x80 // mov eax, -2147483648 + JMP LBB4_13 + +LBB4_6: + WORD $0x8945; BYTE $0xcb // mov r11d, r9d + LONG $0xf8e38341 // and r11d, -8 + LONG $0xf8438d49 // lea rax, [r11 - 8] + WORD $0x8949; BYTE $0xc0 // mov r8, rax + LONG $0x03e8c149 // shr r8, 3 + LONG $0x01c08349 // add r8, 1 + WORD $0x8548; BYTE $0xc0 // test rax, rax + JE LBB4_7 + WORD $0x894d; BYTE $0xc2 // mov r10, r8 + LONG $0xfee28349 // and r10, -2 + WORD $0xf749; BYTE $0xda // neg r10 + LONG $0x4d6f0f66; BYTE $0x00 // movdqa xmm1, oword 0[rbp] /* [rip + .LCPI4_0] */ + LONG $0x456f0f66; BYTE $0x10 // movdqa xmm0, oword 16[rbp] /* [rip + .LCPI4_1] */ + WORD $0xc031 // xor eax, eax + LONG $0xd06f0f66 // movdqa xmm2, xmm0 + LONG $0xd96f0f66 // movdqa xmm3, xmm1 + +LBB4_9: + LONG $0x246f0ff3; BYTE $0x87 // movdqu xmm4, oword [rdi + 4*rax] + LONG $0x6c6f0ff3; WORD $0x1087 // movdqu xmm5, oword [rdi + 4*rax + 16] + LONG $0x746f0ff3; WORD $0x2087 // movdqu xmm6, oword [rdi + 4*rax + 32] + LONG $0x7c6f0ff3; WORD $0x3087 // movdqu xmm7, oword [rdi + 4*rax + 48] + LONG $0x39380f66; BYTE $0xc4 // pminsd xmm0, xmm4 + LONG $0x39380f66; BYTE $0xd5 // pminsd xmm2, xmm5 + LONG $0x3d380f66; BYTE $0xcc // pmaxsd xmm1, xmm4 + LONG $0x3d380f66; BYTE $0xdd // pmaxsd xmm3, xmm5 + LONG $0x39380f66; BYTE $0xc6 // pminsd xmm0, xmm6 + LONG $0x39380f66; BYTE $0xd7 // pminsd xmm2, xmm7 + LONG $0x3d380f66; BYTE $0xce // pmaxsd xmm1, xmm6 + LONG $0x3d380f66; BYTE $0xdf // pmaxsd xmm3, xmm7 + LONG $0x10c08348 // add rax, 16 + LONG $0x02c28349 // add r10, 2 + JNE LBB4_9 + LONG $0x01c0f641 // test r8b, 1 + JE LBB4_12 + +LBB4_11: + LONG $0x246f0ff3; BYTE $0x87 // movdqu xmm4, oword [rdi + 4*rax] + LONG $0x6c6f0ff3; WORD $0x1087 // movdqu xmm5, oword [rdi + 4*rax + 16] + LONG $0x3d380f66; BYTE $0xdd // pmaxsd xmm3, xmm5 + LONG $0x3d380f66; BYTE $0xcc // pmaxsd xmm1, xmm4 + LONG $0x39380f66; BYTE $0xd5 // pminsd xmm2, xmm5 + LONG $0x39380f66; BYTE $0xc4 // pminsd xmm0, xmm4 + +LBB4_12: + LONG $0x39380f66; BYTE $0xc2 // pminsd xmm0, xmm2 + LONG $0x3d380f66; BYTE $0xcb // pmaxsd xmm1, xmm3 + LONG $0xd1700f66; BYTE $0x4e // pshufd xmm2, xmm1, 78 + LONG $0x3d380f66; BYTE $0xd1 // pmaxsd xmm2, xmm1 + LONG $0xca700f66; BYTE $0xe5 // pshufd xmm1, xmm2, 229 + LONG $0x3d380f66; BYTE $0xca // pmaxsd xmm1, xmm2 + LONG $0xc87e0f66 // movd eax, xmm1 + LONG $0xc8700f66; BYTE $0x4e // pshufd xmm1, xmm0, 78 + LONG $0x39380f66; BYTE $0xc8 // pminsd xmm1, xmm0 + LONG $0xc1700f66; BYTE $0xe5 // pshufd xmm0, xmm1, 229 + LONG $0x39380f66; BYTE $0xc1 // pminsd xmm0, xmm1 + LONG $0x7e0f4166; BYTE $0xc0 // movd r8d, xmm0 + WORD $0x394d; BYTE $0xcb // cmp r11, r9 + JE LBB4_13 + +LBB4_4: + WORD $0xc689 // mov esi, eax + +LBB4_5: + LONG $0x9f048b42 // mov eax, dword [rdi + 4*r11] + WORD $0x3941; BYTE $0xc0 // cmp r8d, eax + LONG $0xc04f0f44 // cmovg r8d, eax + WORD $0xc639 // cmp esi, eax + WORD $0x4d0f; BYTE $0xc6 // cmovge eax, esi + LONG $0x01c38349 // add r11, 1 + WORD $0xc689 // mov esi, eax + WORD $0x394d; BYTE $0xd9 // cmp r9, r11 + JNE LBB4_5 + +LBB4_13: + WORD $0x0189 // mov dword [rcx], eax + WORD $0x8944; BYTE $0x02 // mov dword [rdx], r8d + RET + +LBB4_7: + LONG $0x4d6f0f66; BYTE $0x00 // movdqa xmm1, oword 0[rbp] /* [rip + .LCPI4_0] */ + LONG $0x456f0f66; BYTE $0x10 // movdqa xmm0, oword 16[rbp] /* [rip + .LCPI4_1] */ + WORD $0xc031 // xor eax, eax + LONG $0xd06f0f66 // movdqa xmm2, xmm0 + LONG $0xd96f0f66 // movdqa xmm3, xmm1 + LONG $0x01c0f641 // test r8b, 1 + JNE LBB4_11 + JMP LBB4_12 + +TEXT ·_uint32_max_min_sse4(SB), $0-32 + + MOVQ values+0(FP), DI + MOVQ length+8(FP), SI + MOVQ minout+16(FP), DX + MOVQ maxout+24(FP), CX + + WORD $0xf685 // test esi, esi + JLE LBB5_1 + WORD $0x8941; BYTE $0xf1 // mov r9d, esi + WORD $0xfe83; BYTE $0x07 // cmp esi, 7 + JA LBB5_6 + WORD $0x3145; BYTE $0xdb // xor r11d, r11d + LONG $0xffffb841; WORD $0xffff // mov r8d, -1 + WORD $0xf631 // xor esi, esi + JMP LBB5_4 + +LBB5_1: + LONG $0xffffb841; WORD $0xffff // mov r8d, -1 + WORD $0xf631 // xor esi, esi + JMP LBB5_13 + +LBB5_6: + WORD $0x8945; BYTE $0xcb // mov r11d, r9d + LONG $0xf8e38341 // and r11d, -8 + LONG $0xf8438d49 // lea rax, [r11 - 8] + WORD $0x8949; BYTE $0xc0 // mov r8, rax + LONG $0x03e8c149 // shr r8, 3 + LONG $0x01c08349 // add r8, 1 + WORD $0x8548; BYTE $0xc0 // test rax, rax + JE LBB5_7 + WORD $0x894d; BYTE $0xc2 // mov r10, r8 + LONG $0xfee28349 // and r10, -2 + WORD $0xf749; BYTE $0xda // neg r10 + LONG $0xc9ef0f66 // pxor xmm1, xmm1 + LONG $0xc0760f66 // pcmpeqd xmm0, xmm0 + WORD $0xc031 // xor eax, eax + LONG $0xd2760f66 // pcmpeqd xmm2, xmm2 + LONG $0xdbef0f66 // pxor xmm3, xmm3 + +LBB5_9: + LONG $0x246f0ff3; BYTE $0x87 // movdqu xmm4, oword [rdi + 4*rax] + LONG $0x6c6f0ff3; WORD $0x1087 // movdqu xmm5, oword [rdi + 4*rax + 16] + LONG $0x746f0ff3; WORD $0x2087 // movdqu xmm6, oword [rdi + 4*rax + 32] + LONG $0x7c6f0ff3; WORD $0x3087 // movdqu xmm7, oword [rdi + 4*rax + 48] + LONG $0x3b380f66; BYTE $0xc4 // pminud xmm0, xmm4 + LONG $0x3b380f66; BYTE $0xd5 // pminud xmm2, xmm5 + LONG $0x3f380f66; BYTE $0xcc // pmaxud xmm1, xmm4 + LONG $0x3f380f66; BYTE $0xdd // pmaxud xmm3, xmm5 + LONG $0x3b380f66; BYTE $0xc6 // pminud xmm0, xmm6 + LONG $0x3b380f66; BYTE $0xd7 // pminud xmm2, xmm7 + LONG $0x3f380f66; BYTE $0xce // pmaxud xmm1, xmm6 + LONG $0x3f380f66; BYTE $0xdf // pmaxud xmm3, xmm7 + LONG $0x10c08348 // add rax, 16 + LONG $0x02c28349 // add r10, 2 + JNE LBB5_9 + LONG $0x01c0f641 // test r8b, 1 + JE LBB5_12 + +LBB5_11: + LONG $0x246f0ff3; BYTE $0x87 // movdqu xmm4, oword [rdi + 4*rax] + LONG $0x6c6f0ff3; WORD $0x1087 // movdqu xmm5, oword [rdi + 4*rax + 16] + LONG $0x3f380f66; BYTE $0xdd // pmaxud xmm3, xmm5 + LONG $0x3f380f66; BYTE $0xcc // pmaxud xmm1, xmm4 + LONG $0x3b380f66; BYTE $0xd5 // pminud xmm2, xmm5 + LONG $0x3b380f66; BYTE $0xc4 // pminud xmm0, xmm4 + +LBB5_12: + LONG $0x3b380f66; BYTE $0xc2 // pminud xmm0, xmm2 + LONG $0x3f380f66; BYTE $0xcb // pmaxud xmm1, xmm3 + LONG $0xd1700f66; BYTE $0x4e // pshufd xmm2, xmm1, 78 + LONG $0x3f380f66; BYTE $0xd1 // pmaxud xmm2, xmm1 + LONG $0xca700f66; BYTE $0xe5 // pshufd xmm1, xmm2, 229 + LONG $0x3f380f66; BYTE $0xca // pmaxud xmm1, xmm2 + LONG $0xce7e0f66 // movd esi, xmm1 + LONG $0xc8700f66; BYTE $0x4e // pshufd xmm1, xmm0, 78 + LONG $0x3b380f66; BYTE $0xc8 // pminud xmm1, xmm0 + LONG $0xc1700f66; BYTE $0xe5 // pshufd xmm0, xmm1, 229 + LONG $0x3b380f66; BYTE $0xc1 // pminud xmm0, xmm1 + LONG $0x7e0f4166; BYTE $0xc0 // movd r8d, xmm0 + WORD $0x394d; BYTE $0xcb // cmp r11, r9 + JE LBB5_13 + +LBB5_4: + WORD $0xf089 // mov eax, esi + +LBB5_5: + LONG $0x9f348b42 // mov esi, dword [rdi + 4*r11] + WORD $0x3941; BYTE $0xf0 // cmp r8d, esi + LONG $0xc6430f44 // cmovae r8d, esi + WORD $0xf039 // cmp eax, esi + WORD $0x470f; BYTE $0xf0 // cmova esi, eax + LONG $0x01c38349 // add r11, 1 + WORD $0xf089 // mov eax, esi + WORD $0x394d; BYTE $0xd9 // cmp r9, r11 + JNE LBB5_5 + +LBB5_13: + WORD $0x3189 // mov dword [rcx], esi + WORD $0x8944; BYTE $0x02 // mov dword [rdx], r8d + RET + +LBB5_7: + LONG $0xc9ef0f66 // pxor xmm1, xmm1 + LONG $0xc0760f66 // pcmpeqd xmm0, xmm0 + WORD $0xc031 // xor eax, eax + LONG $0xd2760f66 // pcmpeqd xmm2, xmm2 + LONG $0xdbef0f66 // pxor xmm3, xmm3 + LONG $0x01c0f641 // test r8b, 1 + JNE LBB5_11 + JMP LBB5_12 + +DATA LCDATA4<>+0x000(SB)/8, $0x8000000000000000 +DATA LCDATA4<>+0x008(SB)/8, $0x8000000000000000 +DATA LCDATA4<>+0x010(SB)/8, $0x7fffffffffffffff +DATA LCDATA4<>+0x018(SB)/8, $0x7fffffffffffffff +GLOBL LCDATA4<>(SB), 8, $32 + +TEXT ·_int64_max_min_sse4(SB), $0-32 + + MOVQ values+0(FP), DI + MOVQ length+8(FP), SI + MOVQ minout+16(FP), DX + MOVQ maxout+24(FP), CX + LEAQ LCDATA4<>(SB), BP + + QUAD $0xffffffffffffb849; WORD $0x7fff // mov r8, 9223372036854775807 + WORD $0xf685 // test esi, esi + JLE LBB6_1 + WORD $0x8941; BYTE $0xf1 // mov r9d, esi + WORD $0xfe83; BYTE $0x03 // cmp esi, 3 + JA LBB6_6 + LONG $0x01708d49 // lea rsi, [r8 + 1] + WORD $0x3145; BYTE $0xdb // xor r11d, r11d + JMP LBB6_4 + +LBB6_1: + LONG $0x01708d49 // lea rsi, [r8 + 1] + JMP LBB6_13 + +LBB6_6: + WORD $0x8945; BYTE $0xcb // mov r11d, r9d + LONG $0xfce38341 // and r11d, -4 + LONG $0xfc438d49 // lea rax, [r11 - 4] + WORD $0x8949; BYTE $0xc0 // mov r8, rax + LONG $0x02e8c149 // shr r8, 2 + LONG $0x01c08349 // add r8, 1 + WORD $0x8548; BYTE $0xc0 // test rax, rax + JE LBB6_7 + WORD $0x894d; BYTE $0xc2 // mov r10, r8 + LONG $0xfee28349 // and r10, -2 + WORD $0xf749; BYTE $0xda // neg r10 + LONG $0x6f0f4466; WORD $0x004d // movdqa xmm9, oword 0[rbp] /* [rip + .LCPI6_0] */ + LONG $0x6f0f4466; WORD $0x1045 // movdqa xmm8, oword 16[rbp] /* [rip + .LCPI6_1] */ + WORD $0xc031 // xor eax, eax + LONG $0x6f0f4166; BYTE $0xd0 // movdqa xmm2, xmm8 + LONG $0x6f0f4166; BYTE $0xf1 // movdqa xmm6, xmm9 + +LBB6_9: + LONG $0x3c6f0ff3; BYTE $0xc7 // movdqu xmm7, oword [rdi + 8*rax] + LONG $0xc76f0f66 // movdqa xmm0, xmm7 + LONG $0x380f4166; WORD $0xc037 // pcmpgtq xmm0, xmm8 + LONG $0xe76f0f66 // movdqa xmm4, xmm7 + LONG $0x380f4166; WORD $0xe015 // blendvpd xmm4, xmm8, xmm0 + LONG $0x4c6f0ff3; WORD $0x10c7 // movdqu xmm1, oword [rdi + 8*rax + 16] + LONG $0xc16f0f66 // movdqa xmm0, xmm1 + LONG $0x37380f66; BYTE $0xc2 // pcmpgtq xmm0, xmm2 + LONG $0xe96f0f66 // movdqa xmm5, xmm1 + LONG $0x15380f66; BYTE $0xea // blendvpd xmm5, xmm2, xmm0 + LONG $0x6f0f4166; BYTE $0xc1 // movdqa xmm0, xmm9 + LONG $0x37380f66; BYTE $0xc7 // pcmpgtq xmm0, xmm7 + LONG $0x380f4166; WORD $0xf915 // blendvpd xmm7, xmm9, xmm0 + LONG $0xc66f0f66 // movdqa xmm0, xmm6 + LONG $0x37380f66; BYTE $0xc1 // pcmpgtq xmm0, xmm1 + LONG $0x15380f66; BYTE $0xce // blendvpd xmm1, xmm6, xmm0 + LONG $0x5c6f0ff3; WORD $0x20c7 // movdqu xmm3, oword [rdi + 8*rax + 32] + LONG $0xc36f0f66 // movdqa xmm0, xmm3 + LONG $0x37380f66; BYTE $0xc4 // pcmpgtq xmm0, xmm4 + LONG $0x6f0f4466; BYTE $0xc3 // movdqa xmm8, xmm3 + LONG $0x380f4466; WORD $0xc415 // blendvpd xmm8, xmm4, xmm0 + LONG $0x646f0ff3; WORD $0x30c7 // movdqu xmm4, oword [rdi + 8*rax + 48] + LONG $0xc46f0f66 // movdqa xmm0, xmm4 + LONG $0x37380f66; BYTE $0xc5 // pcmpgtq xmm0, xmm5 + LONG $0xd46f0f66 // movdqa xmm2, xmm4 + LONG $0x15380f66; BYTE $0xd5 // blendvpd xmm2, xmm5, xmm0 + LONG $0xc7280f66 // movapd xmm0, xmm7 + LONG $0x37380f66; BYTE $0xc3 // pcmpgtq xmm0, xmm3 + LONG $0x15380f66; BYTE $0xdf // blendvpd xmm3, xmm7, xmm0 + LONG $0xc1280f66 // movapd xmm0, xmm1 + LONG $0x37380f66; BYTE $0xc4 // pcmpgtq xmm0, xmm4 + LONG $0x15380f66; BYTE $0xe1 // blendvpd xmm4, xmm1, xmm0 + LONG $0x08c08348 // add rax, 8 + LONG $0x280f4466; BYTE $0xcb // movapd xmm9, xmm3 + LONG $0xf4280f66 // movapd xmm6, xmm4 + LONG $0x02c28349 // add r10, 2 + JNE LBB6_9 + LONG $0x01c0f641 // test r8b, 1 + JE LBB6_12 + +LBB6_11: + LONG $0x4c6f0ff3; WORD $0x10c7 // movdqu xmm1, oword [rdi + 8*rax + 16] + LONG $0xc4280f66 // movapd xmm0, xmm4 + LONG $0x37380f66; BYTE $0xc1 // pcmpgtq xmm0, xmm1 + LONG $0xe96f0f66 // movdqa xmm5, xmm1 + LONG $0x15380f66; BYTE $0xec // blendvpd xmm5, xmm4, xmm0 + LONG $0x246f0ff3; BYTE $0xc7 // movdqu xmm4, oword [rdi + 8*rax] + LONG $0xc3280f66 // movapd xmm0, xmm3 + LONG $0x37380f66; BYTE $0xc4 // pcmpgtq xmm0, xmm4 + LONG $0xf46f0f66 // movdqa xmm6, xmm4 + LONG $0x15380f66; BYTE $0xf3 // blendvpd xmm6, xmm3, xmm0 + LONG $0xc16f0f66 // movdqa xmm0, xmm1 + LONG $0x37380f66; BYTE $0xc2 // pcmpgtq xmm0, xmm2 + LONG $0x15380f66; BYTE $0xca // blendvpd xmm1, xmm2, xmm0 + LONG $0xc46f0f66 // movdqa xmm0, xmm4 + LONG $0x380f4166; WORD $0xc037 // pcmpgtq xmm0, xmm8 + LONG $0x380f4166; WORD $0xe015 // blendvpd xmm4, xmm8, xmm0 + LONG $0x280f4466; BYTE $0xc4 // movapd xmm8, xmm4 + LONG $0xd1280f66 // movapd xmm2, xmm1 + LONG $0xde280f66 // movapd xmm3, xmm6 + LONG $0xe5280f66 // movapd xmm4, xmm5 + +LBB6_12: + LONG $0xc3280f66 // movapd xmm0, xmm3 + LONG $0x37380f66; BYTE $0xc4 // pcmpgtq xmm0, xmm4 + LONG $0x15380f66; BYTE $0xe3 // blendvpd xmm4, xmm3, xmm0 + LONG $0xcc700f66; BYTE $0x4e // pshufd xmm1, xmm4, 78 + LONG $0xc46f0f66 // movdqa xmm0, xmm4 + LONG $0x37380f66; BYTE $0xc1 // pcmpgtq xmm0, xmm1 + LONG $0x15380f66; BYTE $0xcc // blendvpd xmm1, xmm4, xmm0 + LONG $0x7e0f4866; BYTE $0xce // movq rsi, xmm1 + LONG $0xc26f0f66 // movdqa xmm0, xmm2 + LONG $0x380f4166; WORD $0xc037 // pcmpgtq xmm0, xmm8 + LONG $0x380f4166; WORD $0xd015 // blendvpd xmm2, xmm8, xmm0 + LONG $0xca700f66; BYTE $0x4e // pshufd xmm1, xmm2, 78 + LONG $0xc16f0f66 // movdqa xmm0, xmm1 + LONG $0x37380f66; BYTE $0xc2 // pcmpgtq xmm0, xmm2 + LONG $0x15380f66; BYTE $0xca // blendvpd xmm1, xmm2, xmm0 + LONG $0x7e0f4966; BYTE $0xc8 // movq r8, xmm1 + WORD $0x394d; BYTE $0xcb // cmp r11, r9 + JE LBB6_13 + +LBB6_4: + WORD $0x8948; BYTE $0xf0 // mov rax, rsi + +LBB6_5: + LONG $0xdf348b4a // mov rsi, qword [rdi + 8*r11] + WORD $0x3949; BYTE $0xf0 // cmp r8, rsi + LONG $0xc64f0f4c // cmovg r8, rsi + WORD $0x3948; BYTE $0xf0 // cmp rax, rsi + LONG $0xf04d0f48 // cmovge rsi, rax + LONG $0x01c38349 // add r11, 1 + WORD $0x8948; BYTE $0xf0 // mov rax, rsi + WORD $0x394d; BYTE $0xd9 // cmp r9, r11 + JNE LBB6_5 + +LBB6_13: + WORD $0x8948; BYTE $0x31 // mov qword [rcx], rsi + WORD $0x894c; BYTE $0x02 // mov qword [rdx], r8 + RET + +LBB6_7: + LONG $0x5d280f66; BYTE $0x00 // movapd xmm3, oword 0[rbp] /* [rip + .LCPI6_0] */ + LONG $0x6f0f4466; WORD $0x1045 // movdqa xmm8, oword 16[rbp] /* [rip + .LCPI6_1] */ + WORD $0xc031 // xor eax, eax + LONG $0x6f0f4166; BYTE $0xd0 // movdqa xmm2, xmm8 + LONG $0xe3280f66 // movapd xmm4, xmm3 + LONG $0x01c0f641 // test r8b, 1 + JNE LBB6_11 + JMP LBB6_12 + +DATA LCDATA5<>+0x000(SB)/8, $0x8000000000000000 +DATA LCDATA5<>+0x008(SB)/8, $0x8000000000000000 +GLOBL LCDATA5<>(SB), 8, $16 + +TEXT ·_uint64_max_min_sse4(SB), $0-32 + + MOVQ values+0(FP), DI + MOVQ length+8(FP), SI + MOVQ minout+16(FP), DX + MOVQ maxout+24(FP), CX + LEAQ LCDATA5<>(SB), BP + + WORD $0xf685 // test esi, esi + JLE LBB7_1 + WORD $0x8941; BYTE $0xf1 // mov r9d, esi + WORD $0xfe83; BYTE $0x03 // cmp esi, 3 + JA LBB7_6 + LONG $0xffc0c749; WORD $0xffff; BYTE $0xff // mov r8, -1 + WORD $0x3145; BYTE $0xdb // xor r11d, r11d + WORD $0xc031 // xor eax, eax + JMP LBB7_4 + +LBB7_1: + LONG $0xffc0c749; WORD $0xffff; BYTE $0xff // mov r8, -1 + WORD $0xc031 // xor eax, eax + JMP LBB7_13 + +LBB7_6: + WORD $0x8945; BYTE $0xcb // mov r11d, r9d + LONG $0xfce38341 // and r11d, -4 + LONG $0xfc438d49 // lea rax, [r11 - 4] + WORD $0x8949; BYTE $0xc0 // mov r8, rax + LONG $0x02e8c149 // shr r8, 2 + LONG $0x01c08349 // add r8, 1 + WORD $0x8548; BYTE $0xc0 // test rax, rax + JE LBB7_7 + WORD $0x894d; BYTE $0xc2 // mov r10, r8 + LONG $0xfee28349 // and r10, -2 + WORD $0xf749; BYTE $0xda // neg r10 + LONG $0xef0f4566; BYTE $0xc9 // pxor xmm9, xmm9 + LONG $0x760f4566; BYTE $0xd2 // pcmpeqd xmm10, xmm10 + WORD $0xc031 // xor eax, eax + LONG $0x6f0f4466; WORD $0x0045 // movdqa xmm8, oword 0[rbp] /* [rip + .LCPI7_0] */ + LONG $0x760f4566; BYTE $0xdb // pcmpeqd xmm11, xmm11 + LONG $0xef0f4566; BYTE $0xe4 // pxor xmm12, xmm12 + +LBB7_9: + LONG $0x6f0f4166; BYTE $0xd2 // movdqa xmm2, xmm10 + LONG $0xef0f4166; BYTE $0xd0 // pxor xmm2, xmm8 + LONG $0x246f0ff3; BYTE $0xc7 // movdqu xmm4, oword [rdi + 8*rax] + LONG $0x6c6f0ff3; WORD $0x10c7 // movdqu xmm5, oword [rdi + 8*rax + 16] + LONG $0x6f0f44f3; WORD $0xc76c; BYTE $0x20 // movdqu xmm13, oword [rdi + 8*rax + 32] + LONG $0xc46f0f66 // movdqa xmm0, xmm4 + LONG $0xef0f4166; BYTE $0xc0 // pxor xmm0, xmm8 + LONG $0x6f0f4166; BYTE $0xc9 // movdqa xmm1, xmm9 + LONG $0xef0f4166; BYTE $0xc8 // pxor xmm1, xmm8 + LONG $0x37380f66; BYTE $0xc8 // pcmpgtq xmm1, xmm0 + LONG $0x37380f66; BYTE $0xc2 // pcmpgtq xmm0, xmm2 + LONG $0xdc6f0f66 // movdqa xmm3, xmm4 + LONG $0x380f4166; WORD $0xda15 // blendvpd xmm3, xmm10, xmm0 + LONG $0x746f0ff3; WORD $0x30c7 // movdqu xmm6, oword [rdi + 8*rax + 48] + LONG $0x6f0f4166; BYTE $0xfb // movdqa xmm7, xmm11 + LONG $0xef0f4166; BYTE $0xf8 // pxor xmm7, xmm8 + LONG $0xc56f0f66 // movdqa xmm0, xmm5 + LONG $0xef0f4166; BYTE $0xc0 // pxor xmm0, xmm8 + LONG $0x6f0f4166; BYTE $0xd4 // movdqa xmm2, xmm12 + LONG $0xef0f4166; BYTE $0xd0 // pxor xmm2, xmm8 + LONG $0x37380f66; BYTE $0xd0 // pcmpgtq xmm2, xmm0 + LONG $0x37380f66; BYTE $0xc7 // pcmpgtq xmm0, xmm7 + LONG $0xfd6f0f66 // movdqa xmm7, xmm5 + LONG $0x380f4166; WORD $0xfb15 // blendvpd xmm7, xmm11, xmm0 + LONG $0xc16f0f66 // movdqa xmm0, xmm1 + LONG $0x380f4166; WORD $0xe115 // blendvpd xmm4, xmm9, xmm0 + LONG $0xc26f0f66 // movdqa xmm0, xmm2 + LONG $0x380f4166; WORD $0xec15 // blendvpd xmm5, xmm12, xmm0 + LONG $0xd3280f66 // movapd xmm2, xmm3 + LONG $0x570f4166; BYTE $0xd0 // xorpd xmm2, xmm8 + LONG $0x6f0f4166; BYTE $0xc5 // movdqa xmm0, xmm13 + LONG $0xef0f4166; BYTE $0xc0 // pxor xmm0, xmm8 + LONG $0xcc280f66 // movapd xmm1, xmm4 + LONG $0x570f4166; BYTE $0xc8 // xorpd xmm1, xmm8 + LONG $0x37380f66; BYTE $0xc8 // pcmpgtq xmm1, xmm0 + LONG $0x37380f66; BYTE $0xc2 // pcmpgtq xmm0, xmm2 + LONG $0x6f0f4566; BYTE $0xd5 // movdqa xmm10, xmm13 + LONG $0x380f4466; WORD $0xd315 // blendvpd xmm10, xmm3, xmm0 + LONG $0xdf280f66 // movapd xmm3, xmm7 + LONG $0x570f4166; BYTE $0xd8 // xorpd xmm3, xmm8 + LONG $0xc66f0f66 // movdqa xmm0, xmm6 + LONG $0xef0f4166; BYTE $0xc0 // pxor xmm0, xmm8 + LONG $0xd5280f66 // movapd xmm2, xmm5 + LONG $0x570f4166; BYTE $0xd0 // xorpd xmm2, xmm8 + LONG $0x37380f66; BYTE $0xd0 // pcmpgtq xmm2, xmm0 + LONG $0x37380f66; BYTE $0xc3 // pcmpgtq xmm0, xmm3 + LONG $0x6f0f4466; BYTE $0xde // movdqa xmm11, xmm6 + LONG $0x380f4466; WORD $0xdf15 // blendvpd xmm11, xmm7, xmm0 + LONG $0xc16f0f66 // movdqa xmm0, xmm1 + LONG $0x380f4466; WORD $0xec15 // blendvpd xmm13, xmm4, xmm0 + LONG $0xc26f0f66 // movdqa xmm0, xmm2 + LONG $0x15380f66; BYTE $0xf5 // blendvpd xmm6, xmm5, xmm0 + LONG $0x08c08348 // add rax, 8 + LONG $0x280f4566; BYTE $0xcd // movapd xmm9, xmm13 + LONG $0x280f4466; BYTE $0xe6 // movapd xmm12, xmm6 + LONG $0x02c28349 // add r10, 2 + JNE LBB7_9 + LONG $0x01c0f641 // test r8b, 1 + JE LBB7_12 + +LBB7_11: + LONG $0x24100f66; BYTE $0xc7 // movupd xmm4, oword [rdi + 8*rax] + LONG $0x5c100f66; WORD $0x10c7 // movupd xmm3, oword [rdi + 8*rax + 16] + LONG $0x6d280f66; BYTE $0x00 // movapd xmm5, oword 0[rbp] /* [rip + .LCPI7_0] */ + LONG $0xc6280f66 // movapd xmm0, xmm6 + LONG $0xc5570f66 // xorpd xmm0, xmm5 + LONG $0xcb280f66 // movapd xmm1, xmm3 + LONG $0xcd570f66 // xorpd xmm1, xmm5 + LONG $0x37380f66; BYTE $0xc1 // pcmpgtq xmm0, xmm1 + LONG $0xfb280f66 // movapd xmm7, xmm3 + LONG $0x15380f66; BYTE $0xfe // blendvpd xmm7, xmm6, xmm0 + LONG $0x280f4166; BYTE $0xc5 // movapd xmm0, xmm13 + LONG $0xc5570f66 // xorpd xmm0, xmm5 + LONG $0xd4280f66 // movapd xmm2, xmm4 + LONG $0xd5570f66 // xorpd xmm2, xmm5 + LONG $0x37380f66; BYTE $0xc2 // pcmpgtq xmm0, xmm2 + LONG $0xf4280f66 // movapd xmm6, xmm4 + LONG $0x380f4166; WORD $0xf515 // blendvpd xmm6, xmm13, xmm0 + LONG $0x280f4166; BYTE $0xc3 // movapd xmm0, xmm11 + LONG $0xc5570f66 // xorpd xmm0, xmm5 + LONG $0x37380f66; BYTE $0xc8 // pcmpgtq xmm1, xmm0 + LONG $0xc16f0f66 // movdqa xmm0, xmm1 + LONG $0x380f4166; WORD $0xdb15 // blendvpd xmm3, xmm11, xmm0 + LONG $0x570f4166; BYTE $0xea // xorpd xmm5, xmm10 + LONG $0x37380f66; BYTE $0xd5 // pcmpgtq xmm2, xmm5 + LONG $0xc26f0f66 // movdqa xmm0, xmm2 + LONG $0x380f4166; WORD $0xe215 // blendvpd xmm4, xmm10, xmm0 + LONG $0x280f4466; BYTE $0xd4 // movapd xmm10, xmm4 + LONG $0x280f4466; BYTE $0xdb // movapd xmm11, xmm3 + LONG $0x280f4466; BYTE $0xee // movapd xmm13, xmm6 + LONG $0xf7280f66 // movapd xmm6, xmm7 + +LBB7_12: + LONG $0x4d280f66; BYTE $0x00 // movapd xmm1, oword 0[rbp] /* [rip + .LCPI7_0] */ + LONG $0xd6280f66 // movapd xmm2, xmm6 + LONG $0xd1570f66 // xorpd xmm2, xmm1 + LONG $0x280f4166; BYTE $0xc5 // movapd xmm0, xmm13 + LONG $0xc1570f66 // xorpd xmm0, xmm1 + LONG $0x37380f66; BYTE $0xc2 // pcmpgtq xmm0, xmm2 + LONG $0x380f4166; WORD $0xf515 // blendvpd xmm6, xmm13, xmm0 + LONG $0xd6700f66; BYTE $0x4e // pshufd xmm2, xmm6, 78 + LONG $0xc6280f66 // movapd xmm0, xmm6 + LONG $0xc1570f66 // xorpd xmm0, xmm1 + LONG $0xda6f0f66 // movdqa xmm3, xmm2 + LONG $0xd9ef0f66 // pxor xmm3, xmm1 + LONG $0x37380f66; BYTE $0xc3 // pcmpgtq xmm0, xmm3 + LONG $0x15380f66; BYTE $0xd6 // blendvpd xmm2, xmm6, xmm0 + LONG $0x7e0f4866; BYTE $0xd0 // movq rax, xmm2 + LONG $0x6f0f4166; BYTE $0xd2 // movdqa xmm2, xmm10 + LONG $0xd1ef0f66 // pxor xmm2, xmm1 + LONG $0x6f0f4166; BYTE $0xc3 // movdqa xmm0, xmm11 + LONG $0xc1ef0f66 // pxor xmm0, xmm1 + LONG $0x37380f66; BYTE $0xc2 // pcmpgtq xmm0, xmm2 + LONG $0x380f4566; WORD $0xda15 // blendvpd xmm11, xmm10, xmm0 + LONG $0x700f4166; WORD $0x4ed3 // pshufd xmm2, xmm11, 78 + LONG $0x6f0f4166; BYTE $0xc3 // movdqa xmm0, xmm11 + LONG $0xc1ef0f66 // pxor xmm0, xmm1 + LONG $0xcaef0f66 // pxor xmm1, xmm2 + LONG $0x37380f66; BYTE $0xc8 // pcmpgtq xmm1, xmm0 + LONG $0xc16f0f66 // movdqa xmm0, xmm1 + LONG $0x380f4166; WORD $0xd315 // blendvpd xmm2, xmm11, xmm0 + LONG $0x7e0f4966; BYTE $0xd0 // movq r8, xmm2 + WORD $0x394d; BYTE $0xcb // cmp r11, r9 + JE LBB7_13 + +LBB7_4: + WORD $0x8948; BYTE $0xc6 // mov rsi, rax + +LBB7_5: + LONG $0xdf048b4a // mov rax, qword [rdi + 8*r11] + WORD $0x3949; BYTE $0xc0 // cmp r8, rax + LONG $0xc0430f4c // cmovae r8, rax + WORD $0x3948; BYTE $0xc6 // cmp rsi, rax + LONG $0xc6470f48 // cmova rax, rsi + LONG $0x01c38349 // add r11, 1 + WORD $0x8948; BYTE $0xc6 // mov rsi, rax + WORD $0x394d; BYTE $0xd9 // cmp r9, r11 + JNE LBB7_5 + +LBB7_13: + WORD $0x8948; BYTE $0x01 // mov qword [rcx], rax + WORD $0x894c; BYTE $0x02 // mov qword [rdx], r8 + RET + +LBB7_7: + LONG $0x570f4566; BYTE $0xed // xorpd xmm13, xmm13 + LONG $0x760f4566; BYTE $0xd2 // pcmpeqd xmm10, xmm10 + WORD $0xc031 // xor eax, eax + LONG $0x760f4566; BYTE $0xdb // pcmpeqd xmm11, xmm11 + LONG $0xf6570f66 // xorpd xmm6, xmm6 + LONG $0x01c0f641 // test r8b, 1 + JNE LBB7_11 + JMP LBB7_12 diff --git a/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints.go b/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints.go new file mode 100644 index 000000000..1666df129 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints.go @@ -0,0 +1,407 @@ +// Code generated by transpose_ints.go.tmpl. DO NOT EDIT. + +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package utils + +// when we upgrade to support go1.18, this can be massively simplified by using +// Go Generics, but since we aren't supporting go1.18 yet, I didn't want to use +// them here so we can maintain the backwards compatibility. + +func transposeInt8Int8(src []int8, dest []int8, transposeMap []int32) { + for i, s := range src { + dest[i] = int8(transposeMap[s]) + } +} + +func transposeInt8Uint8(src []int8, dest []uint8, transposeMap []int32) { + for i, s := range src { + dest[i] = uint8(transposeMap[s]) + } +} + +func transposeInt8Int16(src []int8, dest []int16, transposeMap []int32) { + for i, s := range src { + dest[i] = int16(transposeMap[s]) + } +} + +func transposeInt8Uint16(src []int8, dest []uint16, transposeMap []int32) { + for i, s := range src { + dest[i] = uint16(transposeMap[s]) + } +} + +func transposeInt8Int32(src []int8, dest []int32, transposeMap []int32) { + for i, s := range src { + dest[i] = int32(transposeMap[s]) + } +} + +func transposeInt8Uint32(src []int8, dest []uint32, transposeMap []int32) { + for i, s := range src { + dest[i] = uint32(transposeMap[s]) + } +} + +func transposeInt8Int64(src []int8, dest []int64, transposeMap []int32) { + for i, s := range src { + dest[i] = int64(transposeMap[s]) + } +} + +func transposeInt8Uint64(src []int8, dest []uint64, transposeMap []int32) { + for i, s := range src { + dest[i] = uint64(transposeMap[s]) + } +} + +func transposeUint8Int8(src []uint8, dest []int8, transposeMap []int32) { + for i, s := range src { + dest[i] = int8(transposeMap[s]) + } +} + +func transposeUint8Uint8(src []uint8, dest []uint8, transposeMap []int32) { + for i, s := range src { + dest[i] = uint8(transposeMap[s]) + } +} + +func transposeUint8Int16(src []uint8, dest []int16, transposeMap []int32) { + for i, s := range src { + dest[i] = int16(transposeMap[s]) + } +} + +func transposeUint8Uint16(src []uint8, dest []uint16, transposeMap []int32) { + for i, s := range src { + dest[i] = uint16(transposeMap[s]) + } +} + +func transposeUint8Int32(src []uint8, dest []int32, transposeMap []int32) { + for i, s := range src { + dest[i] = int32(transposeMap[s]) + } +} + +func transposeUint8Uint32(src []uint8, dest []uint32, transposeMap []int32) { + for i, s := range src { + dest[i] = uint32(transposeMap[s]) + } +} + +func transposeUint8Int64(src []uint8, dest []int64, transposeMap []int32) { + for i, s := range src { + dest[i] = int64(transposeMap[s]) + } +} + +func transposeUint8Uint64(src []uint8, dest []uint64, transposeMap []int32) { + for i, s := range src { + dest[i] = uint64(transposeMap[s]) + } +} + +func transposeInt16Int8(src []int16, dest []int8, transposeMap []int32) { + for i, s := range src { + dest[i] = int8(transposeMap[s]) + } +} + +func transposeInt16Uint8(src []int16, dest []uint8, transposeMap []int32) { + for i, s := range src { + dest[i] = uint8(transposeMap[s]) + } +} + +func transposeInt16Int16(src []int16, dest []int16, transposeMap []int32) { + for i, s := range src { + dest[i] = int16(transposeMap[s]) + } +} + +func transposeInt16Uint16(src []int16, dest []uint16, transposeMap []int32) { + for i, s := range src { + dest[i] = uint16(transposeMap[s]) + } +} + +func transposeInt16Int32(src []int16, dest []int32, transposeMap []int32) { + for i, s := range src { + dest[i] = int32(transposeMap[s]) + } +} + +func transposeInt16Uint32(src []int16, dest []uint32, transposeMap []int32) { + for i, s := range src { + dest[i] = uint32(transposeMap[s]) + } +} + +func transposeInt16Int64(src []int16, dest []int64, transposeMap []int32) { + for i, s := range src { + dest[i] = int64(transposeMap[s]) + } +} + +func transposeInt16Uint64(src []int16, dest []uint64, transposeMap []int32) { + for i, s := range src { + dest[i] = uint64(transposeMap[s]) + } +} + +func transposeUint16Int8(src []uint16, dest []int8, transposeMap []int32) { + for i, s := range src { + dest[i] = int8(transposeMap[s]) + } +} + +func transposeUint16Uint8(src []uint16, dest []uint8, transposeMap []int32) { + for i, s := range src { + dest[i] = uint8(transposeMap[s]) + } +} + +func transposeUint16Int16(src []uint16, dest []int16, transposeMap []int32) { + for i, s := range src { + dest[i] = int16(transposeMap[s]) + } +} + +func transposeUint16Uint16(src []uint16, dest []uint16, transposeMap []int32) { + for i, s := range src { + dest[i] = uint16(transposeMap[s]) + } +} + +func transposeUint16Int32(src []uint16, dest []int32, transposeMap []int32) { + for i, s := range src { + dest[i] = int32(transposeMap[s]) + } +} + +func transposeUint16Uint32(src []uint16, dest []uint32, transposeMap []int32) { + for i, s := range src { + dest[i] = uint32(transposeMap[s]) + } +} + +func transposeUint16Int64(src []uint16, dest []int64, transposeMap []int32) { + for i, s := range src { + dest[i] = int64(transposeMap[s]) + } +} + +func transposeUint16Uint64(src []uint16, dest []uint64, transposeMap []int32) { + for i, s := range src { + dest[i] = uint64(transposeMap[s]) + } +} + +func transposeInt32Int8(src []int32, dest []int8, transposeMap []int32) { + for i, s := range src { + dest[i] = int8(transposeMap[s]) + } +} + +func transposeInt32Uint8(src []int32, dest []uint8, transposeMap []int32) { + for i, s := range src { + dest[i] = uint8(transposeMap[s]) + } +} + +func transposeInt32Int16(src []int32, dest []int16, transposeMap []int32) { + for i, s := range src { + dest[i] = int16(transposeMap[s]) + } +} + +func transposeInt32Uint16(src []int32, dest []uint16, transposeMap []int32) { + for i, s := range src { + dest[i] = uint16(transposeMap[s]) + } +} + +func transposeInt32Int32(src []int32, dest []int32, transposeMap []int32) { + for i, s := range src { + dest[i] = int32(transposeMap[s]) + } +} + +func transposeInt32Uint32(src []int32, dest []uint32, transposeMap []int32) { + for i, s := range src { + dest[i] = uint32(transposeMap[s]) + } +} + +func transposeInt32Int64(src []int32, dest []int64, transposeMap []int32) { + for i, s := range src { + dest[i] = int64(transposeMap[s]) + } +} + +func transposeInt32Uint64(src []int32, dest []uint64, transposeMap []int32) { + for i, s := range src { + dest[i] = uint64(transposeMap[s]) + } +} + +func transposeUint32Int8(src []uint32, dest []int8, transposeMap []int32) { + for i, s := range src { + dest[i] = int8(transposeMap[s]) + } +} + +func transposeUint32Uint8(src []uint32, dest []uint8, transposeMap []int32) { + for i, s := range src { + dest[i] = uint8(transposeMap[s]) + } +} + +func transposeUint32Int16(src []uint32, dest []int16, transposeMap []int32) { + for i, s := range src { + dest[i] = int16(transposeMap[s]) + } +} + +func transposeUint32Uint16(src []uint32, dest []uint16, transposeMap []int32) { + for i, s := range src { + dest[i] = uint16(transposeMap[s]) + } +} + +func transposeUint32Int32(src []uint32, dest []int32, transposeMap []int32) { + for i, s := range src { + dest[i] = int32(transposeMap[s]) + } +} + +func transposeUint32Uint32(src []uint32, dest []uint32, transposeMap []int32) { + for i, s := range src { + dest[i] = uint32(transposeMap[s]) + } +} + +func transposeUint32Int64(src []uint32, dest []int64, transposeMap []int32) { + for i, s := range src { + dest[i] = int64(transposeMap[s]) + } +} + +func transposeUint32Uint64(src []uint32, dest []uint64, transposeMap []int32) { + for i, s := range src { + dest[i] = uint64(transposeMap[s]) + } +} + +func transposeInt64Int8(src []int64, dest []int8, transposeMap []int32) { + for i, s := range src { + dest[i] = int8(transposeMap[s]) + } +} + +func transposeInt64Uint8(src []int64, dest []uint8, transposeMap []int32) { + for i, s := range src { + dest[i] = uint8(transposeMap[s]) + } +} + +func transposeInt64Int16(src []int64, dest []int16, transposeMap []int32) { + for i, s := range src { + dest[i] = int16(transposeMap[s]) + } +} + +func transposeInt64Uint16(src []int64, dest []uint16, transposeMap []int32) { + for i, s := range src { + dest[i] = uint16(transposeMap[s]) + } +} + +func transposeInt64Int32(src []int64, dest []int32, transposeMap []int32) { + for i, s := range src { + dest[i] = int32(transposeMap[s]) + } +} + +func transposeInt64Uint32(src []int64, dest []uint32, transposeMap []int32) { + for i, s := range src { + dest[i] = uint32(transposeMap[s]) + } +} + +func transposeInt64Int64(src []int64, dest []int64, transposeMap []int32) { + for i, s := range src { + dest[i] = int64(transposeMap[s]) + } +} + +func transposeInt64Uint64(src []int64, dest []uint64, transposeMap []int32) { + for i, s := range src { + dest[i] = uint64(transposeMap[s]) + } +} + +func transposeUint64Int8(src []uint64, dest []int8, transposeMap []int32) { + for i, s := range src { + dest[i] = int8(transposeMap[s]) + } +} + +func transposeUint64Uint8(src []uint64, dest []uint8, transposeMap []int32) { + for i, s := range src { + dest[i] = uint8(transposeMap[s]) + } +} + +func transposeUint64Int16(src []uint64, dest []int16, transposeMap []int32) { + for i, s := range src { + dest[i] = int16(transposeMap[s]) + } +} + +func transposeUint64Uint16(src []uint64, dest []uint16, transposeMap []int32) { + for i, s := range src { + dest[i] = uint16(transposeMap[s]) + } +} + +func transposeUint64Int32(src []uint64, dest []int32, transposeMap []int32) { + for i, s := range src { + dest[i] = int32(transposeMap[s]) + } +} + +func transposeUint64Uint32(src []uint64, dest []uint32, transposeMap []int32) { + for i, s := range src { + dest[i] = uint32(transposeMap[s]) + } +} + +func transposeUint64Int64(src []uint64, dest []int64, transposeMap []int32) { + for i, s := range src { + dest[i] = int64(transposeMap[s]) + } +} + +func transposeUint64Uint64(src []uint64, dest []uint64, transposeMap []int32) { + for i, s := range src { + dest[i] = uint64(transposeMap[s]) + } +} diff --git a/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints.go.tmpl b/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints.go.tmpl new file mode 100644 index 000000000..680ae1ee7 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints.go.tmpl @@ -0,0 +1,34 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package utils + +{{ $typelist := .In }} +{{range .In}} +{{ $src := .Type }} +{{ $srcName := .Name }} +{{ range $typelist }} +{{ $dest := .Type }} +{{ $destName := .Name }} + +func transpose{{ $srcName }}{{ $destName }}(src []{{$src}}, dest []{{$dest}}, transposeMap []int32) { + for i, s := range src { + dest[i] = {{ $dest }}(transposeMap[s]) + } +} + +{{ end }} +{{ end }} diff --git a/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints.tmpldata b/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints.tmpldata new file mode 100644 index 000000000..72eaf300c --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints.tmpldata @@ -0,0 +1,34 @@ +[ + { + "Name": "Int8", + "Type": "int8" + }, + { + "Name": "Uint8", + "Type": "uint8" + }, + { + "Name": "Int16", + "Type": "int16" + }, + { + "Name": "Uint16", + "Type": "uint16" + }, + { + "Name": "Int32", + "Type": "int32" + }, + { + "Name": "Uint32", + "Type": "uint32" + }, + { + "Name": "Int64", + "Type": "int64" + }, + { + "Name": "Uint64", + "Type": "uint64" + } +] diff --git a/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_amd64.go b/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_amd64.go new file mode 100644 index 000000000..d4433d368 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_amd64.go @@ -0,0 +1,325 @@ +// Code generated by transpose_ints_amd64.go.tmpl. DO NOT EDIT. + +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !noasm + +package utils + +import ( + "golang.org/x/sys/cpu" +) + +var ( + TransposeInt8Int8 func([]int8, []int8, []int32) + TransposeInt8Uint8 func([]int8, []uint8, []int32) + TransposeInt8Int16 func([]int8, []int16, []int32) + TransposeInt8Uint16 func([]int8, []uint16, []int32) + TransposeInt8Int32 func([]int8, []int32, []int32) + TransposeInt8Uint32 func([]int8, []uint32, []int32) + TransposeInt8Int64 func([]int8, []int64, []int32) + TransposeInt8Uint64 func([]int8, []uint64, []int32) + + TransposeUint8Int8 func([]uint8, []int8, []int32) + TransposeUint8Uint8 func([]uint8, []uint8, []int32) + TransposeUint8Int16 func([]uint8, []int16, []int32) + TransposeUint8Uint16 func([]uint8, []uint16, []int32) + TransposeUint8Int32 func([]uint8, []int32, []int32) + TransposeUint8Uint32 func([]uint8, []uint32, []int32) + TransposeUint8Int64 func([]uint8, []int64, []int32) + TransposeUint8Uint64 func([]uint8, []uint64, []int32) + + TransposeInt16Int8 func([]int16, []int8, []int32) + TransposeInt16Uint8 func([]int16, []uint8, []int32) + TransposeInt16Int16 func([]int16, []int16, []int32) + TransposeInt16Uint16 func([]int16, []uint16, []int32) + TransposeInt16Int32 func([]int16, []int32, []int32) + TransposeInt16Uint32 func([]int16, []uint32, []int32) + TransposeInt16Int64 func([]int16, []int64, []int32) + TransposeInt16Uint64 func([]int16, []uint64, []int32) + + TransposeUint16Int8 func([]uint16, []int8, []int32) + TransposeUint16Uint8 func([]uint16, []uint8, []int32) + TransposeUint16Int16 func([]uint16, []int16, []int32) + TransposeUint16Uint16 func([]uint16, []uint16, []int32) + TransposeUint16Int32 func([]uint16, []int32, []int32) + TransposeUint16Uint32 func([]uint16, []uint32, []int32) + TransposeUint16Int64 func([]uint16, []int64, []int32) + TransposeUint16Uint64 func([]uint16, []uint64, []int32) + + TransposeInt32Int8 func([]int32, []int8, []int32) + TransposeInt32Uint8 func([]int32, []uint8, []int32) + TransposeInt32Int16 func([]int32, []int16, []int32) + TransposeInt32Uint16 func([]int32, []uint16, []int32) + TransposeInt32Int32 func([]int32, []int32, []int32) + TransposeInt32Uint32 func([]int32, []uint32, []int32) + TransposeInt32Int64 func([]int32, []int64, []int32) + TransposeInt32Uint64 func([]int32, []uint64, []int32) + + TransposeUint32Int8 func([]uint32, []int8, []int32) + TransposeUint32Uint8 func([]uint32, []uint8, []int32) + TransposeUint32Int16 func([]uint32, []int16, []int32) + TransposeUint32Uint16 func([]uint32, []uint16, []int32) + TransposeUint32Int32 func([]uint32, []int32, []int32) + TransposeUint32Uint32 func([]uint32, []uint32, []int32) + TransposeUint32Int64 func([]uint32, []int64, []int32) + TransposeUint32Uint64 func([]uint32, []uint64, []int32) + + TransposeInt64Int8 func([]int64, []int8, []int32) + TransposeInt64Uint8 func([]int64, []uint8, []int32) + TransposeInt64Int16 func([]int64, []int16, []int32) + TransposeInt64Uint16 func([]int64, []uint16, []int32) + TransposeInt64Int32 func([]int64, []int32, []int32) + TransposeInt64Uint32 func([]int64, []uint32, []int32) + TransposeInt64Int64 func([]int64, []int64, []int32) + TransposeInt64Uint64 func([]int64, []uint64, []int32) + + TransposeUint64Int8 func([]uint64, []int8, []int32) + TransposeUint64Uint8 func([]uint64, []uint8, []int32) + TransposeUint64Int16 func([]uint64, []int16, []int32) + TransposeUint64Uint16 func([]uint64, []uint16, []int32) + TransposeUint64Int32 func([]uint64, []int32, []int32) + TransposeUint64Uint32 func([]uint64, []uint32, []int32) + TransposeUint64Int64 func([]uint64, []int64, []int32) + TransposeUint64Uint64 func([]uint64, []uint64, []int32) +) + +func init() { + if cpu.X86.HasAVX2 { + + TransposeInt8Int8 = transposeInt8Int8avx2 + TransposeInt8Uint8 = transposeInt8Uint8avx2 + TransposeInt8Int16 = transposeInt8Int16avx2 + TransposeInt8Uint16 = transposeInt8Uint16avx2 + TransposeInt8Int32 = transposeInt8Int32avx2 + TransposeInt8Uint32 = transposeInt8Uint32avx2 + TransposeInt8Int64 = transposeInt8Int64avx2 + TransposeInt8Uint64 = transposeInt8Uint64avx2 + + TransposeUint8Int8 = transposeUint8Int8avx2 + TransposeUint8Uint8 = transposeUint8Uint8avx2 + TransposeUint8Int16 = transposeUint8Int16avx2 + TransposeUint8Uint16 = transposeUint8Uint16avx2 + TransposeUint8Int32 = transposeUint8Int32avx2 + TransposeUint8Uint32 = transposeUint8Uint32avx2 + TransposeUint8Int64 = transposeUint8Int64avx2 + TransposeUint8Uint64 = transposeUint8Uint64avx2 + + TransposeInt16Int8 = transposeInt16Int8avx2 + TransposeInt16Uint8 = transposeInt16Uint8avx2 + TransposeInt16Int16 = transposeInt16Int16avx2 + TransposeInt16Uint16 = transposeInt16Uint16avx2 + TransposeInt16Int32 = transposeInt16Int32avx2 + TransposeInt16Uint32 = transposeInt16Uint32avx2 + TransposeInt16Int64 = transposeInt16Int64avx2 + TransposeInt16Uint64 = transposeInt16Uint64avx2 + + TransposeUint16Int8 = transposeUint16Int8avx2 + TransposeUint16Uint8 = transposeUint16Uint8avx2 + TransposeUint16Int16 = transposeUint16Int16avx2 + TransposeUint16Uint16 = transposeUint16Uint16avx2 + TransposeUint16Int32 = transposeUint16Int32avx2 + TransposeUint16Uint32 = transposeUint16Uint32avx2 + TransposeUint16Int64 = transposeUint16Int64avx2 + TransposeUint16Uint64 = transposeUint16Uint64avx2 + + TransposeInt32Int8 = transposeInt32Int8avx2 + TransposeInt32Uint8 = transposeInt32Uint8avx2 + TransposeInt32Int16 = transposeInt32Int16avx2 + TransposeInt32Uint16 = transposeInt32Uint16avx2 + TransposeInt32Int32 = transposeInt32Int32avx2 + TransposeInt32Uint32 = transposeInt32Uint32avx2 + TransposeInt32Int64 = transposeInt32Int64avx2 + TransposeInt32Uint64 = transposeInt32Uint64avx2 + + TransposeUint32Int8 = transposeUint32Int8avx2 + TransposeUint32Uint8 = transposeUint32Uint8avx2 + TransposeUint32Int16 = transposeUint32Int16avx2 + TransposeUint32Uint16 = transposeUint32Uint16avx2 + TransposeUint32Int32 = transposeUint32Int32avx2 + TransposeUint32Uint32 = transposeUint32Uint32avx2 + TransposeUint32Int64 = transposeUint32Int64avx2 + TransposeUint32Uint64 = transposeUint32Uint64avx2 + + TransposeInt64Int8 = transposeInt64Int8avx2 + TransposeInt64Uint8 = transposeInt64Uint8avx2 + TransposeInt64Int16 = transposeInt64Int16avx2 + TransposeInt64Uint16 = transposeInt64Uint16avx2 + TransposeInt64Int32 = transposeInt64Int32avx2 + TransposeInt64Uint32 = transposeInt64Uint32avx2 + TransposeInt64Int64 = transposeInt64Int64avx2 + TransposeInt64Uint64 = transposeInt64Uint64avx2 + + TransposeUint64Int8 = transposeUint64Int8avx2 + TransposeUint64Uint8 = transposeUint64Uint8avx2 + TransposeUint64Int16 = transposeUint64Int16avx2 + TransposeUint64Uint16 = transposeUint64Uint16avx2 + TransposeUint64Int32 = transposeUint64Int32avx2 + TransposeUint64Uint32 = transposeUint64Uint32avx2 + TransposeUint64Int64 = transposeUint64Int64avx2 + TransposeUint64Uint64 = transposeUint64Uint64avx2 + + } else if cpu.X86.HasSSE42 { + + TransposeInt8Int8 = transposeInt8Int8sse4 + TransposeInt8Uint8 = transposeInt8Uint8sse4 + TransposeInt8Int16 = transposeInt8Int16sse4 + TransposeInt8Uint16 = transposeInt8Uint16sse4 + TransposeInt8Int32 = transposeInt8Int32sse4 + TransposeInt8Uint32 = transposeInt8Uint32sse4 + TransposeInt8Int64 = transposeInt8Int64sse4 + TransposeInt8Uint64 = transposeInt8Uint64sse4 + + TransposeUint8Int8 = transposeUint8Int8sse4 + TransposeUint8Uint8 = transposeUint8Uint8sse4 + TransposeUint8Int16 = transposeUint8Int16sse4 + TransposeUint8Uint16 = transposeUint8Uint16sse4 + TransposeUint8Int32 = transposeUint8Int32sse4 + TransposeUint8Uint32 = transposeUint8Uint32sse4 + TransposeUint8Int64 = transposeUint8Int64sse4 + TransposeUint8Uint64 = transposeUint8Uint64sse4 + + TransposeInt16Int8 = transposeInt16Int8sse4 + TransposeInt16Uint8 = transposeInt16Uint8sse4 + TransposeInt16Int16 = transposeInt16Int16sse4 + TransposeInt16Uint16 = transposeInt16Uint16sse4 + TransposeInt16Int32 = transposeInt16Int32sse4 + TransposeInt16Uint32 = transposeInt16Uint32sse4 + TransposeInt16Int64 = transposeInt16Int64sse4 + TransposeInt16Uint64 = transposeInt16Uint64sse4 + + TransposeUint16Int8 = transposeUint16Int8sse4 + TransposeUint16Uint8 = transposeUint16Uint8sse4 + TransposeUint16Int16 = transposeUint16Int16sse4 + TransposeUint16Uint16 = transposeUint16Uint16sse4 + TransposeUint16Int32 = transposeUint16Int32sse4 + TransposeUint16Uint32 = transposeUint16Uint32sse4 + TransposeUint16Int64 = transposeUint16Int64sse4 + TransposeUint16Uint64 = transposeUint16Uint64sse4 + + TransposeInt32Int8 = transposeInt32Int8sse4 + TransposeInt32Uint8 = transposeInt32Uint8sse4 + TransposeInt32Int16 = transposeInt32Int16sse4 + TransposeInt32Uint16 = transposeInt32Uint16sse4 + TransposeInt32Int32 = transposeInt32Int32sse4 + TransposeInt32Uint32 = transposeInt32Uint32sse4 + TransposeInt32Int64 = transposeInt32Int64sse4 + TransposeInt32Uint64 = transposeInt32Uint64sse4 + + TransposeUint32Int8 = transposeUint32Int8sse4 + TransposeUint32Uint8 = transposeUint32Uint8sse4 + TransposeUint32Int16 = transposeUint32Int16sse4 + TransposeUint32Uint16 = transposeUint32Uint16sse4 + TransposeUint32Int32 = transposeUint32Int32sse4 + TransposeUint32Uint32 = transposeUint32Uint32sse4 + TransposeUint32Int64 = transposeUint32Int64sse4 + TransposeUint32Uint64 = transposeUint32Uint64sse4 + + TransposeInt64Int8 = transposeInt64Int8sse4 + TransposeInt64Uint8 = transposeInt64Uint8sse4 + TransposeInt64Int16 = transposeInt64Int16sse4 + TransposeInt64Uint16 = transposeInt64Uint16sse4 + TransposeInt64Int32 = transposeInt64Int32sse4 + TransposeInt64Uint32 = transposeInt64Uint32sse4 + TransposeInt64Int64 = transposeInt64Int64sse4 + TransposeInt64Uint64 = transposeInt64Uint64sse4 + + TransposeUint64Int8 = transposeUint64Int8sse4 + TransposeUint64Uint8 = transposeUint64Uint8sse4 + TransposeUint64Int16 = transposeUint64Int16sse4 + TransposeUint64Uint16 = transposeUint64Uint16sse4 + TransposeUint64Int32 = transposeUint64Int32sse4 + TransposeUint64Uint32 = transposeUint64Uint32sse4 + TransposeUint64Int64 = transposeUint64Int64sse4 + TransposeUint64Uint64 = transposeUint64Uint64sse4 + + } else { + + TransposeInt8Int8 = transposeInt8Int8 + TransposeInt8Uint8 = transposeInt8Uint8 + TransposeInt8Int16 = transposeInt8Int16 + TransposeInt8Uint16 = transposeInt8Uint16 + TransposeInt8Int32 = transposeInt8Int32 + TransposeInt8Uint32 = transposeInt8Uint32 + TransposeInt8Int64 = transposeInt8Int64 + TransposeInt8Uint64 = transposeInt8Uint64 + + TransposeUint8Int8 = transposeUint8Int8 + TransposeUint8Uint8 = transposeUint8Uint8 + TransposeUint8Int16 = transposeUint8Int16 + TransposeUint8Uint16 = transposeUint8Uint16 + TransposeUint8Int32 = transposeUint8Int32 + TransposeUint8Uint32 = transposeUint8Uint32 + TransposeUint8Int64 = transposeUint8Int64 + TransposeUint8Uint64 = transposeUint8Uint64 + + TransposeInt16Int8 = transposeInt16Int8 + TransposeInt16Uint8 = transposeInt16Uint8 + TransposeInt16Int16 = transposeInt16Int16 + TransposeInt16Uint16 = transposeInt16Uint16 + TransposeInt16Int32 = transposeInt16Int32 + TransposeInt16Uint32 = transposeInt16Uint32 + TransposeInt16Int64 = transposeInt16Int64 + TransposeInt16Uint64 = transposeInt16Uint64 + + TransposeUint16Int8 = transposeUint16Int8 + TransposeUint16Uint8 = transposeUint16Uint8 + TransposeUint16Int16 = transposeUint16Int16 + TransposeUint16Uint16 = transposeUint16Uint16 + TransposeUint16Int32 = transposeUint16Int32 + TransposeUint16Uint32 = transposeUint16Uint32 + TransposeUint16Int64 = transposeUint16Int64 + TransposeUint16Uint64 = transposeUint16Uint64 + + TransposeInt32Int8 = transposeInt32Int8 + TransposeInt32Uint8 = transposeInt32Uint8 + TransposeInt32Int16 = transposeInt32Int16 + TransposeInt32Uint16 = transposeInt32Uint16 + TransposeInt32Int32 = transposeInt32Int32 + TransposeInt32Uint32 = transposeInt32Uint32 + TransposeInt32Int64 = transposeInt32Int64 + TransposeInt32Uint64 = transposeInt32Uint64 + + TransposeUint32Int8 = transposeUint32Int8 + TransposeUint32Uint8 = transposeUint32Uint8 + TransposeUint32Int16 = transposeUint32Int16 + TransposeUint32Uint16 = transposeUint32Uint16 + TransposeUint32Int32 = transposeUint32Int32 + TransposeUint32Uint32 = transposeUint32Uint32 + TransposeUint32Int64 = transposeUint32Int64 + TransposeUint32Uint64 = transposeUint32Uint64 + + TransposeInt64Int8 = transposeInt64Int8 + TransposeInt64Uint8 = transposeInt64Uint8 + TransposeInt64Int16 = transposeInt64Int16 + TransposeInt64Uint16 = transposeInt64Uint16 + TransposeInt64Int32 = transposeInt64Int32 + TransposeInt64Uint32 = transposeInt64Uint32 + TransposeInt64Int64 = transposeInt64Int64 + TransposeInt64Uint64 = transposeInt64Uint64 + + TransposeUint64Int8 = transposeUint64Int8 + TransposeUint64Uint8 = transposeUint64Uint8 + TransposeUint64Int16 = transposeUint64Int16 + TransposeUint64Uint16 = transposeUint64Uint16 + TransposeUint64Int32 = transposeUint64Int32 + TransposeUint64Uint32 = transposeUint64Uint32 + TransposeUint64Int64 = transposeUint64Int64 + TransposeUint64Uint64 = transposeUint64Uint64 + + } +} diff --git a/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_amd64.go.tmpl b/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_amd64.go.tmpl new file mode 100644 index 000000000..eac0208e5 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_amd64.go.tmpl @@ -0,0 +1,75 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !noasm +// +build !noasm + +package utils + +import ( + "golang.org/x/sys/cpu" +) + +var ( +{{ $typelist := .In }} +{{range .In}} +{{ $src := .Type -}} +{{ $srcName := .Name -}} +{{ range $typelist -}} +{{ $dest := .Type -}} +{{ $destName := .Name -}} + Transpose{{$srcName}}{{$destName}} func([]{{$src}}, []{{$dest}}, []int32) +{{end}} +{{end}} +) + + +func init() { + if cpu.X86.HasAVX2 { +{{ $typelist := .In }} +{{range .In}} +{{ $src := .Type -}} +{{ $srcName := .Name -}} +{{ range $typelist -}} +{{ $dest := .Type -}} +{{ $destName := .Name -}} + Transpose{{$srcName}}{{$destName}} = transpose{{ $srcName }}{{ $destName }}avx2 +{{end}} +{{end}} + } else if cpu.X86.HasSSE42 { +{{ $typelist := .In }} +{{range .In}} +{{ $src := .Type -}} +{{ $srcName := .Name -}} +{{ range $typelist -}} +{{ $dest := .Type -}} +{{ $destName := .Name -}} + Transpose{{$srcName}}{{$destName}} = transpose{{ $srcName }}{{ $destName }}sse4 +{{end}} +{{end}} + } else { +{{ $typelist := .In }} +{{range .In}} +{{ $src := .Type -}} +{{ $srcName := .Name -}} +{{ range $typelist -}} +{{ $dest := .Type -}} +{{ $destName := .Name -}} + Transpose{{$srcName}}{{$destName}} = transpose{{ $srcName }}{{ $destName }} +{{end}} +{{end}} + } +} diff --git a/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_arm64.go b/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_arm64.go new file mode 100644 index 000000000..cc957cdaa --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_arm64.go @@ -0,0 +1,96 @@ +// Code generated by transpose_ints_s390x.go.tmpl. DO NOT EDIT. + +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !noasm + +package utils + +// if building with the 'noasm' tag, then point to the pure go implementations +var ( + TransposeInt8Int8 = transposeInt8Int8 + TransposeInt8Uint8 = transposeInt8Uint8 + TransposeInt8Int16 = transposeInt8Int16 + TransposeInt8Uint16 = transposeInt8Uint16 + TransposeInt8Int32 = transposeInt8Int32 + TransposeInt8Uint32 = transposeInt8Uint32 + TransposeInt8Int64 = transposeInt8Int64 + TransposeInt8Uint64 = transposeInt8Uint64 + + TransposeUint8Int8 = transposeUint8Int8 + TransposeUint8Uint8 = transposeUint8Uint8 + TransposeUint8Int16 = transposeUint8Int16 + TransposeUint8Uint16 = transposeUint8Uint16 + TransposeUint8Int32 = transposeUint8Int32 + TransposeUint8Uint32 = transposeUint8Uint32 + TransposeUint8Int64 = transposeUint8Int64 + TransposeUint8Uint64 = transposeUint8Uint64 + + TransposeInt16Int8 = transposeInt16Int8 + TransposeInt16Uint8 = transposeInt16Uint8 + TransposeInt16Int16 = transposeInt16Int16 + TransposeInt16Uint16 = transposeInt16Uint16 + TransposeInt16Int32 = transposeInt16Int32 + TransposeInt16Uint32 = transposeInt16Uint32 + TransposeInt16Int64 = transposeInt16Int64 + TransposeInt16Uint64 = transposeInt16Uint64 + + TransposeUint16Int8 = transposeUint16Int8 + TransposeUint16Uint8 = transposeUint16Uint8 + TransposeUint16Int16 = transposeUint16Int16 + TransposeUint16Uint16 = transposeUint16Uint16 + TransposeUint16Int32 = transposeUint16Int32 + TransposeUint16Uint32 = transposeUint16Uint32 + TransposeUint16Int64 = transposeUint16Int64 + TransposeUint16Uint64 = transposeUint16Uint64 + + TransposeInt32Int8 = transposeInt32Int8 + TransposeInt32Uint8 = transposeInt32Uint8 + TransposeInt32Int16 = transposeInt32Int16 + TransposeInt32Uint16 = transposeInt32Uint16 + TransposeInt32Int32 = transposeInt32Int32 + TransposeInt32Uint32 = transposeInt32Uint32 + TransposeInt32Int64 = transposeInt32Int64 + TransposeInt32Uint64 = transposeInt32Uint64 + + TransposeUint32Int8 = transposeUint32Int8 + TransposeUint32Uint8 = transposeUint32Uint8 + TransposeUint32Int16 = transposeUint32Int16 + TransposeUint32Uint16 = transposeUint32Uint16 + TransposeUint32Int32 = transposeUint32Int32 + TransposeUint32Uint32 = transposeUint32Uint32 + TransposeUint32Int64 = transposeUint32Int64 + TransposeUint32Uint64 = transposeUint32Uint64 + + TransposeInt64Int8 = transposeInt64Int8 + TransposeInt64Uint8 = transposeInt64Uint8 + TransposeInt64Int16 = transposeInt64Int16 + TransposeInt64Uint16 = transposeInt64Uint16 + TransposeInt64Int32 = transposeInt64Int32 + TransposeInt64Uint32 = transposeInt64Uint32 + TransposeInt64Int64 = transposeInt64Int64 + TransposeInt64Uint64 = transposeInt64Uint64 + + TransposeUint64Int8 = transposeUint64Int8 + TransposeUint64Uint8 = transposeUint64Uint8 + TransposeUint64Int16 = transposeUint64Int16 + TransposeUint64Uint16 = transposeUint64Uint16 + TransposeUint64Int32 = transposeUint64Int32 + TransposeUint64Uint32 = transposeUint64Uint32 + TransposeUint64Int64 = transposeUint64Int64 + TransposeUint64Uint64 = transposeUint64Uint64 +) diff --git a/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_avx2_amd64.go b/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_avx2_amd64.go new file mode 100644 index 000000000..f1421ddf5 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_avx2_amd64.go @@ -0,0 +1,473 @@ +// Code generated by transpose_ints_simd.go.tmpl. DO NOT EDIT. + +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !noasm + +package utils + +import ( + "unsafe" +) + +//go:noescape +func _transpose_int8_int8_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt8Int8avx2(src []int8, dest []int8, transposeMap []int32) { + _transpose_int8_int8_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int8_uint8_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt8Uint8avx2(src []int8, dest []uint8, transposeMap []int32) { + _transpose_int8_uint8_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int8_int16_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt8Int16avx2(src []int8, dest []int16, transposeMap []int32) { + _transpose_int8_int16_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int8_uint16_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt8Uint16avx2(src []int8, dest []uint16, transposeMap []int32) { + _transpose_int8_uint16_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int8_int32_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt8Int32avx2(src []int8, dest []int32, transposeMap []int32) { + _transpose_int8_int32_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int8_uint32_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt8Uint32avx2(src []int8, dest []uint32, transposeMap []int32) { + _transpose_int8_uint32_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int8_int64_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt8Int64avx2(src []int8, dest []int64, transposeMap []int32) { + _transpose_int8_int64_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int8_uint64_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt8Uint64avx2(src []int8, dest []uint64, transposeMap []int32) { + _transpose_int8_uint64_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint8_int8_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint8Int8avx2(src []uint8, dest []int8, transposeMap []int32) { + _transpose_uint8_int8_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint8_uint8_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint8Uint8avx2(src []uint8, dest []uint8, transposeMap []int32) { + _transpose_uint8_uint8_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint8_int16_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint8Int16avx2(src []uint8, dest []int16, transposeMap []int32) { + _transpose_uint8_int16_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint8_uint16_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint8Uint16avx2(src []uint8, dest []uint16, transposeMap []int32) { + _transpose_uint8_uint16_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint8_int32_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint8Int32avx2(src []uint8, dest []int32, transposeMap []int32) { + _transpose_uint8_int32_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint8_uint32_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint8Uint32avx2(src []uint8, dest []uint32, transposeMap []int32) { + _transpose_uint8_uint32_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint8_int64_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint8Int64avx2(src []uint8, dest []int64, transposeMap []int32) { + _transpose_uint8_int64_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint8_uint64_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint8Uint64avx2(src []uint8, dest []uint64, transposeMap []int32) { + _transpose_uint8_uint64_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int16_int8_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt16Int8avx2(src []int16, dest []int8, transposeMap []int32) { + _transpose_int16_int8_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int16_uint8_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt16Uint8avx2(src []int16, dest []uint8, transposeMap []int32) { + _transpose_int16_uint8_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int16_int16_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt16Int16avx2(src []int16, dest []int16, transposeMap []int32) { + _transpose_int16_int16_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int16_uint16_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt16Uint16avx2(src []int16, dest []uint16, transposeMap []int32) { + _transpose_int16_uint16_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int16_int32_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt16Int32avx2(src []int16, dest []int32, transposeMap []int32) { + _transpose_int16_int32_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int16_uint32_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt16Uint32avx2(src []int16, dest []uint32, transposeMap []int32) { + _transpose_int16_uint32_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int16_int64_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt16Int64avx2(src []int16, dest []int64, transposeMap []int32) { + _transpose_int16_int64_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int16_uint64_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt16Uint64avx2(src []int16, dest []uint64, transposeMap []int32) { + _transpose_int16_uint64_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint16_int8_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint16Int8avx2(src []uint16, dest []int8, transposeMap []int32) { + _transpose_uint16_int8_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint16_uint8_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint16Uint8avx2(src []uint16, dest []uint8, transposeMap []int32) { + _transpose_uint16_uint8_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint16_int16_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint16Int16avx2(src []uint16, dest []int16, transposeMap []int32) { + _transpose_uint16_int16_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint16_uint16_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint16Uint16avx2(src []uint16, dest []uint16, transposeMap []int32) { + _transpose_uint16_uint16_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint16_int32_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint16Int32avx2(src []uint16, dest []int32, transposeMap []int32) { + _transpose_uint16_int32_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint16_uint32_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint16Uint32avx2(src []uint16, dest []uint32, transposeMap []int32) { + _transpose_uint16_uint32_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint16_int64_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint16Int64avx2(src []uint16, dest []int64, transposeMap []int32) { + _transpose_uint16_int64_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint16_uint64_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint16Uint64avx2(src []uint16, dest []uint64, transposeMap []int32) { + _transpose_uint16_uint64_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int32_int8_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt32Int8avx2(src []int32, dest []int8, transposeMap []int32) { + _transpose_int32_int8_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int32_uint8_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt32Uint8avx2(src []int32, dest []uint8, transposeMap []int32) { + _transpose_int32_uint8_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int32_int16_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt32Int16avx2(src []int32, dest []int16, transposeMap []int32) { + _transpose_int32_int16_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int32_uint16_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt32Uint16avx2(src []int32, dest []uint16, transposeMap []int32) { + _transpose_int32_uint16_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int32_int32_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt32Int32avx2(src []int32, dest []int32, transposeMap []int32) { + _transpose_int32_int32_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int32_uint32_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt32Uint32avx2(src []int32, dest []uint32, transposeMap []int32) { + _transpose_int32_uint32_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int32_int64_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt32Int64avx2(src []int32, dest []int64, transposeMap []int32) { + _transpose_int32_int64_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int32_uint64_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt32Uint64avx2(src []int32, dest []uint64, transposeMap []int32) { + _transpose_int32_uint64_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint32_int8_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint32Int8avx2(src []uint32, dest []int8, transposeMap []int32) { + _transpose_uint32_int8_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint32_uint8_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint32Uint8avx2(src []uint32, dest []uint8, transposeMap []int32) { + _transpose_uint32_uint8_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint32_int16_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint32Int16avx2(src []uint32, dest []int16, transposeMap []int32) { + _transpose_uint32_int16_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint32_uint16_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint32Uint16avx2(src []uint32, dest []uint16, transposeMap []int32) { + _transpose_uint32_uint16_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint32_int32_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint32Int32avx2(src []uint32, dest []int32, transposeMap []int32) { + _transpose_uint32_int32_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint32_uint32_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint32Uint32avx2(src []uint32, dest []uint32, transposeMap []int32) { + _transpose_uint32_uint32_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint32_int64_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint32Int64avx2(src []uint32, dest []int64, transposeMap []int32) { + _transpose_uint32_int64_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint32_uint64_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint32Uint64avx2(src []uint32, dest []uint64, transposeMap []int32) { + _transpose_uint32_uint64_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int64_int8_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt64Int8avx2(src []int64, dest []int8, transposeMap []int32) { + _transpose_int64_int8_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int64_uint8_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt64Uint8avx2(src []int64, dest []uint8, transposeMap []int32) { + _transpose_int64_uint8_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int64_int16_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt64Int16avx2(src []int64, dest []int16, transposeMap []int32) { + _transpose_int64_int16_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int64_uint16_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt64Uint16avx2(src []int64, dest []uint16, transposeMap []int32) { + _transpose_int64_uint16_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int64_int32_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt64Int32avx2(src []int64, dest []int32, transposeMap []int32) { + _transpose_int64_int32_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int64_uint32_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt64Uint32avx2(src []int64, dest []uint32, transposeMap []int32) { + _transpose_int64_uint32_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int64_int64_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt64Int64avx2(src []int64, dest []int64, transposeMap []int32) { + _transpose_int64_int64_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int64_uint64_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt64Uint64avx2(src []int64, dest []uint64, transposeMap []int32) { + _transpose_int64_uint64_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint64_int8_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint64Int8avx2(src []uint64, dest []int8, transposeMap []int32) { + _transpose_uint64_int8_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint64_uint8_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint64Uint8avx2(src []uint64, dest []uint8, transposeMap []int32) { + _transpose_uint64_uint8_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint64_int16_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint64Int16avx2(src []uint64, dest []int16, transposeMap []int32) { + _transpose_uint64_int16_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint64_uint16_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint64Uint16avx2(src []uint64, dest []uint16, transposeMap []int32) { + _transpose_uint64_uint16_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint64_int32_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint64Int32avx2(src []uint64, dest []int32, transposeMap []int32) { + _transpose_uint64_int32_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint64_uint32_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint64Uint32avx2(src []uint64, dest []uint32, transposeMap []int32) { + _transpose_uint64_uint32_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint64_int64_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint64Int64avx2(src []uint64, dest []int64, transposeMap []int32) { + _transpose_uint64_int64_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint64_uint64_avx2(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint64Uint64avx2(src []uint64, dest []uint64, transposeMap []int32) { + _transpose_uint64_uint64_avx2(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} diff --git a/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_avx2_amd64.s b/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_avx2_amd64.s new file mode 100644 index 000000000..fbcc101eb --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_avx2_amd64.s @@ -0,0 +1,3074 @@ +//+build !noasm !appengine +// AUTO-GENERATED BY C2GOASM -- DO NOT EDIT + +TEXT ·_transpose_uint8_uint8_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB0_1 + +LBB0_5: + WORD $0xd089 // mov eax, edx + WORD $0xb60f; BYTE $0x17 // movzx edx, byte [rdi] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x1688 // mov byte [rsi], dl + LONG $0x0157b60f // movzx edx, byte [rdi + 1] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x01 // mov byte [rsi + 1], dl + LONG $0x0257b60f // movzx edx, byte [rdi + 2] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x02 // mov byte [rsi + 2], dl + LONG $0x0357b60f // movzx edx, byte [rdi + 3] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x03 // mov byte [rsi + 3], dl + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x04c78348 // add rdi, 4 + LONG $0x04c68348 // add rsi, 4 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB0_5 + +LBB0_1: + WORD $0xd285 // test edx, edx + JLE LBB0_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB0_3: + LONG $0x04b60f42; BYTE $0x07 // movzx eax, byte [rdi + r8] + LONG $0x8104b60f // movzx eax, byte [rcx + 4*rax] + LONG $0x06048842 // mov byte [rsi + r8], al + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB0_3 + +LBB0_4: + RET + +TEXT ·_transpose_int8_uint8_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB1_1 + +LBB1_5: + WORD $0xd089 // mov eax, edx + LONG $0x17be0f48 // movsx rdx, byte [rdi] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x1688 // mov byte [rsi], dl + LONG $0x57be0f48; BYTE $0x01 // movsx rdx, byte [rdi + 1] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x01 // mov byte [rsi + 1], dl + LONG $0x57be0f48; BYTE $0x02 // movsx rdx, byte [rdi + 2] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x02 // mov byte [rsi + 2], dl + LONG $0x57be0f48; BYTE $0x03 // movsx rdx, byte [rdi + 3] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x03 // mov byte [rsi + 3], dl + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x04c78348 // add rdi, 4 + LONG $0x04c68348 // add rsi, 4 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB1_5 + +LBB1_1: + WORD $0xd285 // test edx, edx + JLE LBB1_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB1_3: + LONG $0x04be0f4a; BYTE $0x07 // movsx rax, byte [rdi + r8] + LONG $0x8104b60f // movzx eax, byte [rcx + 4*rax] + LONG $0x06048842 // mov byte [rsi + r8], al + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB1_3 + +LBB1_4: + RET + +TEXT ·_transpose_uint16_uint8_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB2_1 + +LBB2_5: + WORD $0xd089 // mov eax, edx + WORD $0xb70f; BYTE $0x17 // movzx edx, word [rdi] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x1688 // mov byte [rsi], dl + LONG $0x0257b70f // movzx edx, word [rdi + 2] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x01 // mov byte [rsi + 1], dl + LONG $0x0457b70f // movzx edx, word [rdi + 4] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x02 // mov byte [rsi + 2], dl + LONG $0x0657b70f // movzx edx, word [rdi + 6] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x03 // mov byte [rsi + 3], dl + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x08c78348 // add rdi, 8 + LONG $0x04c68348 // add rsi, 4 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB2_5 + +LBB2_1: + WORD $0xd285 // test edx, edx + JLE LBB2_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB2_3: + LONG $0x04b70f42; BYTE $0x47 // movzx eax, word [rdi + 2*r8] + LONG $0x8104b60f // movzx eax, byte [rcx + 4*rax] + LONG $0x06048842 // mov byte [rsi + r8], al + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB2_3 + +LBB2_4: + RET + +TEXT ·_transpose_int16_uint8_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB3_1 + +LBB3_5: + WORD $0xd089 // mov eax, edx + LONG $0x17bf0f48 // movsx rdx, word [rdi] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x1688 // mov byte [rsi], dl + LONG $0x57bf0f48; BYTE $0x02 // movsx rdx, word [rdi + 2] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x01 // mov byte [rsi + 1], dl + LONG $0x57bf0f48; BYTE $0x04 // movsx rdx, word [rdi + 4] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x02 // mov byte [rsi + 2], dl + LONG $0x57bf0f48; BYTE $0x06 // movsx rdx, word [rdi + 6] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x03 // mov byte [rsi + 3], dl + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x08c78348 // add rdi, 8 + LONG $0x04c68348 // add rsi, 4 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB3_5 + +LBB3_1: + WORD $0xd285 // test edx, edx + JLE LBB3_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB3_3: + LONG $0x04bf0f4a; BYTE $0x47 // movsx rax, word [rdi + 2*r8] + LONG $0x8104b60f // movzx eax, byte [rcx + 4*rax] + LONG $0x06048842 // mov byte [rsi + r8], al + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB3_3 + +LBB3_4: + RET + +TEXT ·_transpose_uint32_uint8_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB4_1 + +LBB4_5: + WORD $0xd089 // mov eax, edx + WORD $0x178b // mov edx, dword [rdi] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x1688 // mov byte [rsi], dl + WORD $0x578b; BYTE $0x04 // mov edx, dword [rdi + 4] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x01 // mov byte [rsi + 1], dl + WORD $0x578b; BYTE $0x08 // mov edx, dword [rdi + 8] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x02 // mov byte [rsi + 2], dl + WORD $0x578b; BYTE $0x0c // mov edx, dword [rdi + 12] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x03 // mov byte [rsi + 3], dl + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x10c78348 // add rdi, 16 + LONG $0x04c68348 // add rsi, 4 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB4_5 + +LBB4_1: + WORD $0xd285 // test edx, edx + JLE LBB4_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB4_3: + LONG $0x87048b42 // mov eax, dword [rdi + 4*r8] + LONG $0x8104b60f // movzx eax, byte [rcx + 4*rax] + LONG $0x06048842 // mov byte [rsi + r8], al + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB4_3 + +LBB4_4: + RET + +TEXT ·_transpose_int32_uint8_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB5_1 + +LBB5_5: + WORD $0xd089 // mov eax, edx + WORD $0x6348; BYTE $0x17 // movsxd rdx, dword [rdi] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x1688 // mov byte [rsi], dl + LONG $0x04576348 // movsxd rdx, dword [rdi + 4] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x01 // mov byte [rsi + 1], dl + LONG $0x08576348 // movsxd rdx, dword [rdi + 8] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x02 // mov byte [rsi + 2], dl + LONG $0x0c576348 // movsxd rdx, dword [rdi + 12] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x03 // mov byte [rsi + 3], dl + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x10c78348 // add rdi, 16 + LONG $0x04c68348 // add rsi, 4 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB5_5 + +LBB5_1: + WORD $0xd285 // test edx, edx + JLE LBB5_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB5_3: + LONG $0x8704634a // movsxd rax, dword [rdi + 4*r8] + LONG $0x8104b60f // movzx eax, byte [rcx + 4*rax] + LONG $0x06048842 // mov byte [rsi + r8], al + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB5_3 + +LBB5_4: + RET + +TEXT ·_transpose_uint64_uint8_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB6_1 + +LBB6_5: + WORD $0xd089 // mov eax, edx + WORD $0x8b48; BYTE $0x17 // mov rdx, qword [rdi] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x1688 // mov byte [rsi], dl + LONG $0x08578b48 // mov rdx, qword [rdi + 8] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x01 // mov byte [rsi + 1], dl + LONG $0x10578b48 // mov rdx, qword [rdi + 16] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x02 // mov byte [rsi + 2], dl + LONG $0x18578b48 // mov rdx, qword [rdi + 24] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x03 // mov byte [rsi + 3], dl + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x20c78348 // add rdi, 32 + LONG $0x04c68348 // add rsi, 4 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB6_5 + +LBB6_1: + WORD $0xd285 // test edx, edx + JLE LBB6_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB6_3: + LONG $0xc7048b4a // mov rax, qword [rdi + 8*r8] + LONG $0x8104b60f // movzx eax, byte [rcx + 4*rax] + LONG $0x06048842 // mov byte [rsi + r8], al + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB6_3 + +LBB6_4: + RET + +TEXT ·_transpose_int64_uint8_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB7_1 + +LBB7_5: + WORD $0xd089 // mov eax, edx + WORD $0x8b48; BYTE $0x17 // mov rdx, qword [rdi] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x1688 // mov byte [rsi], dl + LONG $0x08578b48 // mov rdx, qword [rdi + 8] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x01 // mov byte [rsi + 1], dl + LONG $0x10578b48 // mov rdx, qword [rdi + 16] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x02 // mov byte [rsi + 2], dl + LONG $0x18578b48 // mov rdx, qword [rdi + 24] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x03 // mov byte [rsi + 3], dl + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x20c78348 // add rdi, 32 + LONG $0x04c68348 // add rsi, 4 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB7_5 + +LBB7_1: + WORD $0xd285 // test edx, edx + JLE LBB7_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB7_3: + LONG $0xc7048b4a // mov rax, qword [rdi + 8*r8] + LONG $0x8104b60f // movzx eax, byte [rcx + 4*rax] + LONG $0x06048842 // mov byte [rsi + r8], al + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB7_3 + +LBB7_4: + RET + +TEXT ·_transpose_uint8_int8_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB8_1 + +LBB8_5: + WORD $0xd089 // mov eax, edx + WORD $0xb60f; BYTE $0x17 // movzx edx, byte [rdi] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x1688 // mov byte [rsi], dl + LONG $0x0157b60f // movzx edx, byte [rdi + 1] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x01 // mov byte [rsi + 1], dl + LONG $0x0257b60f // movzx edx, byte [rdi + 2] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x02 // mov byte [rsi + 2], dl + LONG $0x0357b60f // movzx edx, byte [rdi + 3] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x03 // mov byte [rsi + 3], dl + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x04c78348 // add rdi, 4 + LONG $0x04c68348 // add rsi, 4 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB8_5 + +LBB8_1: + WORD $0xd285 // test edx, edx + JLE LBB8_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB8_3: + LONG $0x04b60f42; BYTE $0x07 // movzx eax, byte [rdi + r8] + LONG $0x8104b60f // movzx eax, byte [rcx + 4*rax] + LONG $0x06048842 // mov byte [rsi + r8], al + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB8_3 + +LBB8_4: + RET + +TEXT ·_transpose_int8_int8_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB9_1 + +LBB9_5: + WORD $0xd089 // mov eax, edx + LONG $0x17be0f48 // movsx rdx, byte [rdi] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x1688 // mov byte [rsi], dl + LONG $0x57be0f48; BYTE $0x01 // movsx rdx, byte [rdi + 1] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x01 // mov byte [rsi + 1], dl + LONG $0x57be0f48; BYTE $0x02 // movsx rdx, byte [rdi + 2] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x02 // mov byte [rsi + 2], dl + LONG $0x57be0f48; BYTE $0x03 // movsx rdx, byte [rdi + 3] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x03 // mov byte [rsi + 3], dl + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x04c78348 // add rdi, 4 + LONG $0x04c68348 // add rsi, 4 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB9_5 + +LBB9_1: + WORD $0xd285 // test edx, edx + JLE LBB9_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB9_3: + LONG $0x04be0f4a; BYTE $0x07 // movsx rax, byte [rdi + r8] + LONG $0x8104b60f // movzx eax, byte [rcx + 4*rax] + LONG $0x06048842 // mov byte [rsi + r8], al + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB9_3 + +LBB9_4: + RET + +TEXT ·_transpose_uint16_int8_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB10_1 + +LBB10_5: + WORD $0xd089 // mov eax, edx + WORD $0xb70f; BYTE $0x17 // movzx edx, word [rdi] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x1688 // mov byte [rsi], dl + LONG $0x0257b70f // movzx edx, word [rdi + 2] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x01 // mov byte [rsi + 1], dl + LONG $0x0457b70f // movzx edx, word [rdi + 4] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x02 // mov byte [rsi + 2], dl + LONG $0x0657b70f // movzx edx, word [rdi + 6] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x03 // mov byte [rsi + 3], dl + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x08c78348 // add rdi, 8 + LONG $0x04c68348 // add rsi, 4 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB10_5 + +LBB10_1: + WORD $0xd285 // test edx, edx + JLE LBB10_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB10_3: + LONG $0x04b70f42; BYTE $0x47 // movzx eax, word [rdi + 2*r8] + LONG $0x8104b60f // movzx eax, byte [rcx + 4*rax] + LONG $0x06048842 // mov byte [rsi + r8], al + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB10_3 + +LBB10_4: + RET + +TEXT ·_transpose_int16_int8_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB11_1 + +LBB11_5: + WORD $0xd089 // mov eax, edx + LONG $0x17bf0f48 // movsx rdx, word [rdi] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x1688 // mov byte [rsi], dl + LONG $0x57bf0f48; BYTE $0x02 // movsx rdx, word [rdi + 2] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x01 // mov byte [rsi + 1], dl + LONG $0x57bf0f48; BYTE $0x04 // movsx rdx, word [rdi + 4] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x02 // mov byte [rsi + 2], dl + LONG $0x57bf0f48; BYTE $0x06 // movsx rdx, word [rdi + 6] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x03 // mov byte [rsi + 3], dl + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x08c78348 // add rdi, 8 + LONG $0x04c68348 // add rsi, 4 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB11_5 + +LBB11_1: + WORD $0xd285 // test edx, edx + JLE LBB11_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB11_3: + LONG $0x04bf0f4a; BYTE $0x47 // movsx rax, word [rdi + 2*r8] + LONG $0x8104b60f // movzx eax, byte [rcx + 4*rax] + LONG $0x06048842 // mov byte [rsi + r8], al + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB11_3 + +LBB11_4: + RET + +TEXT ·_transpose_uint32_int8_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB12_1 + +LBB12_5: + WORD $0xd089 // mov eax, edx + WORD $0x178b // mov edx, dword [rdi] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x1688 // mov byte [rsi], dl + WORD $0x578b; BYTE $0x04 // mov edx, dword [rdi + 4] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x01 // mov byte [rsi + 1], dl + WORD $0x578b; BYTE $0x08 // mov edx, dword [rdi + 8] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x02 // mov byte [rsi + 2], dl + WORD $0x578b; BYTE $0x0c // mov edx, dword [rdi + 12] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x03 // mov byte [rsi + 3], dl + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x10c78348 // add rdi, 16 + LONG $0x04c68348 // add rsi, 4 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB12_5 + +LBB12_1: + WORD $0xd285 // test edx, edx + JLE LBB12_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB12_3: + LONG $0x87048b42 // mov eax, dword [rdi + 4*r8] + LONG $0x8104b60f // movzx eax, byte [rcx + 4*rax] + LONG $0x06048842 // mov byte [rsi + r8], al + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB12_3 + +LBB12_4: + RET + +TEXT ·_transpose_int32_int8_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB13_1 + +LBB13_5: + WORD $0xd089 // mov eax, edx + WORD $0x6348; BYTE $0x17 // movsxd rdx, dword [rdi] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x1688 // mov byte [rsi], dl + LONG $0x04576348 // movsxd rdx, dword [rdi + 4] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x01 // mov byte [rsi + 1], dl + LONG $0x08576348 // movsxd rdx, dword [rdi + 8] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x02 // mov byte [rsi + 2], dl + LONG $0x0c576348 // movsxd rdx, dword [rdi + 12] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x03 // mov byte [rsi + 3], dl + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x10c78348 // add rdi, 16 + LONG $0x04c68348 // add rsi, 4 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB13_5 + +LBB13_1: + WORD $0xd285 // test edx, edx + JLE LBB13_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB13_3: + LONG $0x8704634a // movsxd rax, dword [rdi + 4*r8] + LONG $0x8104b60f // movzx eax, byte [rcx + 4*rax] + LONG $0x06048842 // mov byte [rsi + r8], al + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB13_3 + +LBB13_4: + RET + +TEXT ·_transpose_uint64_int8_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB14_1 + +LBB14_5: + WORD $0xd089 // mov eax, edx + WORD $0x8b48; BYTE $0x17 // mov rdx, qword [rdi] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x1688 // mov byte [rsi], dl + LONG $0x08578b48 // mov rdx, qword [rdi + 8] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x01 // mov byte [rsi + 1], dl + LONG $0x10578b48 // mov rdx, qword [rdi + 16] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x02 // mov byte [rsi + 2], dl + LONG $0x18578b48 // mov rdx, qword [rdi + 24] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x03 // mov byte [rsi + 3], dl + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x20c78348 // add rdi, 32 + LONG $0x04c68348 // add rsi, 4 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB14_5 + +LBB14_1: + WORD $0xd285 // test edx, edx + JLE LBB14_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB14_3: + LONG $0xc7048b4a // mov rax, qword [rdi + 8*r8] + LONG $0x8104b60f // movzx eax, byte [rcx + 4*rax] + LONG $0x06048842 // mov byte [rsi + r8], al + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB14_3 + +LBB14_4: + RET + +TEXT ·_transpose_int64_int8_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB15_1 + +LBB15_5: + WORD $0xd089 // mov eax, edx + WORD $0x8b48; BYTE $0x17 // mov rdx, qword [rdi] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x1688 // mov byte [rsi], dl + LONG $0x08578b48 // mov rdx, qword [rdi + 8] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x01 // mov byte [rsi + 1], dl + LONG $0x10578b48 // mov rdx, qword [rdi + 16] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x02 // mov byte [rsi + 2], dl + LONG $0x18578b48 // mov rdx, qword [rdi + 24] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x03 // mov byte [rsi + 3], dl + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x20c78348 // add rdi, 32 + LONG $0x04c68348 // add rsi, 4 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB15_5 + +LBB15_1: + WORD $0xd285 // test edx, edx + JLE LBB15_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB15_3: + LONG $0xc7048b4a // mov rax, qword [rdi + 8*r8] + LONG $0x8104b60f // movzx eax, byte [rcx + 4*rax] + LONG $0x06048842 // mov byte [rsi + r8], al + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB15_3 + +LBB15_4: + RET + +TEXT ·_transpose_uint8_uint16_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB16_1 + +LBB16_5: + WORD $0xd089 // mov eax, edx + WORD $0xb60f; BYTE $0x17 // movzx edx, byte [rdi] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + WORD $0x8966; BYTE $0x16 // mov word [rsi], dx + LONG $0x0157b60f // movzx edx, byte [rdi + 1] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x02568966 // mov word [rsi + 2], dx + LONG $0x0257b60f // movzx edx, byte [rdi + 2] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x04568966 // mov word [rsi + 4], dx + LONG $0x0357b60f // movzx edx, byte [rdi + 3] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x06568966 // mov word [rsi + 6], dx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x04c78348 // add rdi, 4 + LONG $0x08c68348 // add rsi, 8 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB16_5 + +LBB16_1: + WORD $0xd285 // test edx, edx + JLE LBB16_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB16_3: + LONG $0x04b60f42; BYTE $0x07 // movzx eax, byte [rdi + r8] + LONG $0x8104b70f // movzx eax, word [rcx + 4*rax] + LONG $0x04894266; BYTE $0x46 // mov word [rsi + 2*r8], ax + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB16_3 + +LBB16_4: + RET + +TEXT ·_transpose_int8_uint16_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB17_1 + +LBB17_5: + WORD $0xd089 // mov eax, edx + LONG $0x17be0f48 // movsx rdx, byte [rdi] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + WORD $0x8966; BYTE $0x16 // mov word [rsi], dx + LONG $0x57be0f48; BYTE $0x01 // movsx rdx, byte [rdi + 1] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x02568966 // mov word [rsi + 2], dx + LONG $0x57be0f48; BYTE $0x02 // movsx rdx, byte [rdi + 2] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x04568966 // mov word [rsi + 4], dx + LONG $0x57be0f48; BYTE $0x03 // movsx rdx, byte [rdi + 3] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x06568966 // mov word [rsi + 6], dx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x04c78348 // add rdi, 4 + LONG $0x08c68348 // add rsi, 8 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB17_5 + +LBB17_1: + WORD $0xd285 // test edx, edx + JLE LBB17_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB17_3: + LONG $0x04be0f4a; BYTE $0x07 // movsx rax, byte [rdi + r8] + LONG $0x8104b70f // movzx eax, word [rcx + 4*rax] + LONG $0x04894266; BYTE $0x46 // mov word [rsi + 2*r8], ax + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB17_3 + +LBB17_4: + RET + +TEXT ·_transpose_uint16_uint16_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB18_1 + +LBB18_5: + WORD $0xd089 // mov eax, edx + WORD $0xb70f; BYTE $0x17 // movzx edx, word [rdi] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + WORD $0x8966; BYTE $0x16 // mov word [rsi], dx + LONG $0x0257b70f // movzx edx, word [rdi + 2] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x02568966 // mov word [rsi + 2], dx + LONG $0x0457b70f // movzx edx, word [rdi + 4] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x04568966 // mov word [rsi + 4], dx + LONG $0x0657b70f // movzx edx, word [rdi + 6] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x06568966 // mov word [rsi + 6], dx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x08c78348 // add rdi, 8 + LONG $0x08c68348 // add rsi, 8 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB18_5 + +LBB18_1: + WORD $0xd285 // test edx, edx + JLE LBB18_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB18_3: + LONG $0x04b70f42; BYTE $0x07 // movzx eax, word [rdi + r8] + LONG $0x8104b70f // movzx eax, word [rcx + 4*rax] + LONG $0x04894266; BYTE $0x06 // mov word [rsi + r8], ax + LONG $0x02c08349 // add r8, 2 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB18_3 + +LBB18_4: + RET + +TEXT ·_transpose_int16_uint16_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB19_1 + +LBB19_5: + WORD $0xd089 // mov eax, edx + LONG $0x17bf0f48 // movsx rdx, word [rdi] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + WORD $0x8966; BYTE $0x16 // mov word [rsi], dx + LONG $0x57bf0f48; BYTE $0x02 // movsx rdx, word [rdi + 2] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x02568966 // mov word [rsi + 2], dx + LONG $0x57bf0f48; BYTE $0x04 // movsx rdx, word [rdi + 4] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x04568966 // mov word [rsi + 4], dx + LONG $0x57bf0f48; BYTE $0x06 // movsx rdx, word [rdi + 6] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x06568966 // mov word [rsi + 6], dx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x08c78348 // add rdi, 8 + LONG $0x08c68348 // add rsi, 8 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB19_5 + +LBB19_1: + WORD $0xd285 // test edx, edx + JLE LBB19_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB19_3: + LONG $0x04bf0f4a; BYTE $0x07 // movsx rax, word [rdi + r8] + LONG $0x8104b70f // movzx eax, word [rcx + 4*rax] + LONG $0x04894266; BYTE $0x06 // mov word [rsi + r8], ax + LONG $0x02c08349 // add r8, 2 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB19_3 + +LBB19_4: + RET + +TEXT ·_transpose_uint32_uint16_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB20_1 + +LBB20_5: + WORD $0xd089 // mov eax, edx + WORD $0x178b // mov edx, dword [rdi] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + WORD $0x8966; BYTE $0x16 // mov word [rsi], dx + WORD $0x578b; BYTE $0x04 // mov edx, dword [rdi + 4] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x02568966 // mov word [rsi + 2], dx + WORD $0x578b; BYTE $0x08 // mov edx, dword [rdi + 8] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x04568966 // mov word [rsi + 4], dx + WORD $0x578b; BYTE $0x0c // mov edx, dword [rdi + 12] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x06568966 // mov word [rsi + 6], dx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x10c78348 // add rdi, 16 + LONG $0x08c68348 // add rsi, 8 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB20_5 + +LBB20_1: + WORD $0xd285 // test edx, edx + JLE LBB20_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB20_3: + LONG $0x47048b42 // mov eax, dword [rdi + 2*r8] + LONG $0x8104b70f // movzx eax, word [rcx + 4*rax] + LONG $0x04894266; BYTE $0x06 // mov word [rsi + r8], ax + LONG $0x02c08349 // add r8, 2 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB20_3 + +LBB20_4: + RET + +TEXT ·_transpose_int32_uint16_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB21_1 + +LBB21_5: + WORD $0xd089 // mov eax, edx + WORD $0x6348; BYTE $0x17 // movsxd rdx, dword [rdi] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + WORD $0x8966; BYTE $0x16 // mov word [rsi], dx + LONG $0x04576348 // movsxd rdx, dword [rdi + 4] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x02568966 // mov word [rsi + 2], dx + LONG $0x08576348 // movsxd rdx, dword [rdi + 8] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x04568966 // mov word [rsi + 4], dx + LONG $0x0c576348 // movsxd rdx, dword [rdi + 12] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x06568966 // mov word [rsi + 6], dx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x10c78348 // add rdi, 16 + LONG $0x08c68348 // add rsi, 8 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB21_5 + +LBB21_1: + WORD $0xd285 // test edx, edx + JLE LBB21_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB21_3: + LONG $0x4704634a // movsxd rax, dword [rdi + 2*r8] + LONG $0x8104b70f // movzx eax, word [rcx + 4*rax] + LONG $0x04894266; BYTE $0x06 // mov word [rsi + r8], ax + LONG $0x02c08349 // add r8, 2 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB21_3 + +LBB21_4: + RET + +TEXT ·_transpose_uint64_uint16_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB22_1 + +LBB22_5: + WORD $0xd089 // mov eax, edx + WORD $0x8b48; BYTE $0x17 // mov rdx, qword [rdi] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + WORD $0x8966; BYTE $0x16 // mov word [rsi], dx + LONG $0x08578b48 // mov rdx, qword [rdi + 8] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x02568966 // mov word [rsi + 2], dx + LONG $0x10578b48 // mov rdx, qword [rdi + 16] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x04568966 // mov word [rsi + 4], dx + LONG $0x18578b48 // mov rdx, qword [rdi + 24] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x06568966 // mov word [rsi + 6], dx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x20c78348 // add rdi, 32 + LONG $0x08c68348 // add rsi, 8 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB22_5 + +LBB22_1: + WORD $0xd285 // test edx, edx + JLE LBB22_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB22_3: + LONG $0x87048b4a // mov rax, qword [rdi + 4*r8] + LONG $0x8104b70f // movzx eax, word [rcx + 4*rax] + LONG $0x04894266; BYTE $0x06 // mov word [rsi + r8], ax + LONG $0x02c08349 // add r8, 2 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB22_3 + +LBB22_4: + RET + +TEXT ·_transpose_int64_uint16_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB23_1 + +LBB23_5: + WORD $0xd089 // mov eax, edx + WORD $0x8b48; BYTE $0x17 // mov rdx, qword [rdi] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + WORD $0x8966; BYTE $0x16 // mov word [rsi], dx + LONG $0x08578b48 // mov rdx, qword [rdi + 8] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x02568966 // mov word [rsi + 2], dx + LONG $0x10578b48 // mov rdx, qword [rdi + 16] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x04568966 // mov word [rsi + 4], dx + LONG $0x18578b48 // mov rdx, qword [rdi + 24] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x06568966 // mov word [rsi + 6], dx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x20c78348 // add rdi, 32 + LONG $0x08c68348 // add rsi, 8 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB23_5 + +LBB23_1: + WORD $0xd285 // test edx, edx + JLE LBB23_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB23_3: + LONG $0x87048b4a // mov rax, qword [rdi + 4*r8] + LONG $0x8104b70f // movzx eax, word [rcx + 4*rax] + LONG $0x04894266; BYTE $0x06 // mov word [rsi + r8], ax + LONG $0x02c08349 // add r8, 2 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB23_3 + +LBB23_4: + RET + +TEXT ·_transpose_uint8_int16_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB24_1 + +LBB24_5: + WORD $0xd089 // mov eax, edx + WORD $0xb60f; BYTE $0x17 // movzx edx, byte [rdi] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + WORD $0x8966; BYTE $0x16 // mov word [rsi], dx + LONG $0x0157b60f // movzx edx, byte [rdi + 1] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x02568966 // mov word [rsi + 2], dx + LONG $0x0257b60f // movzx edx, byte [rdi + 2] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x04568966 // mov word [rsi + 4], dx + LONG $0x0357b60f // movzx edx, byte [rdi + 3] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x06568966 // mov word [rsi + 6], dx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x04c78348 // add rdi, 4 + LONG $0x08c68348 // add rsi, 8 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB24_5 + +LBB24_1: + WORD $0xd285 // test edx, edx + JLE LBB24_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB24_3: + LONG $0x04b60f42; BYTE $0x07 // movzx eax, byte [rdi + r8] + LONG $0x8104b70f // movzx eax, word [rcx + 4*rax] + LONG $0x04894266; BYTE $0x46 // mov word [rsi + 2*r8], ax + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB24_3 + +LBB24_4: + RET + +TEXT ·_transpose_int8_int16_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB25_1 + +LBB25_5: + WORD $0xd089 // mov eax, edx + LONG $0x17be0f48 // movsx rdx, byte [rdi] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + WORD $0x8966; BYTE $0x16 // mov word [rsi], dx + LONG $0x57be0f48; BYTE $0x01 // movsx rdx, byte [rdi + 1] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x02568966 // mov word [rsi + 2], dx + LONG $0x57be0f48; BYTE $0x02 // movsx rdx, byte [rdi + 2] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x04568966 // mov word [rsi + 4], dx + LONG $0x57be0f48; BYTE $0x03 // movsx rdx, byte [rdi + 3] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x06568966 // mov word [rsi + 6], dx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x04c78348 // add rdi, 4 + LONG $0x08c68348 // add rsi, 8 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB25_5 + +LBB25_1: + WORD $0xd285 // test edx, edx + JLE LBB25_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB25_3: + LONG $0x04be0f4a; BYTE $0x07 // movsx rax, byte [rdi + r8] + LONG $0x8104b70f // movzx eax, word [rcx + 4*rax] + LONG $0x04894266; BYTE $0x46 // mov word [rsi + 2*r8], ax + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB25_3 + +LBB25_4: + RET + +TEXT ·_transpose_uint16_int16_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB26_1 + +LBB26_5: + WORD $0xd089 // mov eax, edx + WORD $0xb70f; BYTE $0x17 // movzx edx, word [rdi] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + WORD $0x8966; BYTE $0x16 // mov word [rsi], dx + LONG $0x0257b70f // movzx edx, word [rdi + 2] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x02568966 // mov word [rsi + 2], dx + LONG $0x0457b70f // movzx edx, word [rdi + 4] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x04568966 // mov word [rsi + 4], dx + LONG $0x0657b70f // movzx edx, word [rdi + 6] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x06568966 // mov word [rsi + 6], dx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x08c78348 // add rdi, 8 + LONG $0x08c68348 // add rsi, 8 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB26_5 + +LBB26_1: + WORD $0xd285 // test edx, edx + JLE LBB26_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB26_3: + LONG $0x04b70f42; BYTE $0x07 // movzx eax, word [rdi + r8] + LONG $0x8104b70f // movzx eax, word [rcx + 4*rax] + LONG $0x04894266; BYTE $0x06 // mov word [rsi + r8], ax + LONG $0x02c08349 // add r8, 2 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB26_3 + +LBB26_4: + RET + +TEXT ·_transpose_int16_int16_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB27_1 + +LBB27_5: + WORD $0xd089 // mov eax, edx + LONG $0x17bf0f48 // movsx rdx, word [rdi] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + WORD $0x8966; BYTE $0x16 // mov word [rsi], dx + LONG $0x57bf0f48; BYTE $0x02 // movsx rdx, word [rdi + 2] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x02568966 // mov word [rsi + 2], dx + LONG $0x57bf0f48; BYTE $0x04 // movsx rdx, word [rdi + 4] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x04568966 // mov word [rsi + 4], dx + LONG $0x57bf0f48; BYTE $0x06 // movsx rdx, word [rdi + 6] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x06568966 // mov word [rsi + 6], dx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x08c78348 // add rdi, 8 + LONG $0x08c68348 // add rsi, 8 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB27_5 + +LBB27_1: + WORD $0xd285 // test edx, edx + JLE LBB27_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB27_3: + LONG $0x04bf0f4a; BYTE $0x07 // movsx rax, word [rdi + r8] + LONG $0x8104b70f // movzx eax, word [rcx + 4*rax] + LONG $0x04894266; BYTE $0x06 // mov word [rsi + r8], ax + LONG $0x02c08349 // add r8, 2 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB27_3 + +LBB27_4: + RET + +TEXT ·_transpose_uint32_int16_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB28_1 + +LBB28_5: + WORD $0xd089 // mov eax, edx + WORD $0x178b // mov edx, dword [rdi] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + WORD $0x8966; BYTE $0x16 // mov word [rsi], dx + WORD $0x578b; BYTE $0x04 // mov edx, dword [rdi + 4] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x02568966 // mov word [rsi + 2], dx + WORD $0x578b; BYTE $0x08 // mov edx, dword [rdi + 8] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x04568966 // mov word [rsi + 4], dx + WORD $0x578b; BYTE $0x0c // mov edx, dword [rdi + 12] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x06568966 // mov word [rsi + 6], dx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x10c78348 // add rdi, 16 + LONG $0x08c68348 // add rsi, 8 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB28_5 + +LBB28_1: + WORD $0xd285 // test edx, edx + JLE LBB28_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB28_3: + LONG $0x47048b42 // mov eax, dword [rdi + 2*r8] + LONG $0x8104b70f // movzx eax, word [rcx + 4*rax] + LONG $0x04894266; BYTE $0x06 // mov word [rsi + r8], ax + LONG $0x02c08349 // add r8, 2 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB28_3 + +LBB28_4: + RET + +TEXT ·_transpose_int32_int16_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB29_1 + +LBB29_5: + WORD $0xd089 // mov eax, edx + WORD $0x6348; BYTE $0x17 // movsxd rdx, dword [rdi] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + WORD $0x8966; BYTE $0x16 // mov word [rsi], dx + LONG $0x04576348 // movsxd rdx, dword [rdi + 4] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x02568966 // mov word [rsi + 2], dx + LONG $0x08576348 // movsxd rdx, dword [rdi + 8] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x04568966 // mov word [rsi + 4], dx + LONG $0x0c576348 // movsxd rdx, dword [rdi + 12] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x06568966 // mov word [rsi + 6], dx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x10c78348 // add rdi, 16 + LONG $0x08c68348 // add rsi, 8 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB29_5 + +LBB29_1: + WORD $0xd285 // test edx, edx + JLE LBB29_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB29_3: + LONG $0x4704634a // movsxd rax, dword [rdi + 2*r8] + LONG $0x8104b70f // movzx eax, word [rcx + 4*rax] + LONG $0x04894266; BYTE $0x06 // mov word [rsi + r8], ax + LONG $0x02c08349 // add r8, 2 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB29_3 + +LBB29_4: + RET + +TEXT ·_transpose_uint64_int16_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB30_1 + +LBB30_5: + WORD $0xd089 // mov eax, edx + WORD $0x8b48; BYTE $0x17 // mov rdx, qword [rdi] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + WORD $0x8966; BYTE $0x16 // mov word [rsi], dx + LONG $0x08578b48 // mov rdx, qword [rdi + 8] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x02568966 // mov word [rsi + 2], dx + LONG $0x10578b48 // mov rdx, qword [rdi + 16] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x04568966 // mov word [rsi + 4], dx + LONG $0x18578b48 // mov rdx, qword [rdi + 24] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x06568966 // mov word [rsi + 6], dx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x20c78348 // add rdi, 32 + LONG $0x08c68348 // add rsi, 8 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB30_5 + +LBB30_1: + WORD $0xd285 // test edx, edx + JLE LBB30_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB30_3: + LONG $0x87048b4a // mov rax, qword [rdi + 4*r8] + LONG $0x8104b70f // movzx eax, word [rcx + 4*rax] + LONG $0x04894266; BYTE $0x06 // mov word [rsi + r8], ax + LONG $0x02c08349 // add r8, 2 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB30_3 + +LBB30_4: + RET + +TEXT ·_transpose_int64_int16_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB31_1 + +LBB31_5: + WORD $0xd089 // mov eax, edx + WORD $0x8b48; BYTE $0x17 // mov rdx, qword [rdi] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + WORD $0x8966; BYTE $0x16 // mov word [rsi], dx + LONG $0x08578b48 // mov rdx, qword [rdi + 8] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x02568966 // mov word [rsi + 2], dx + LONG $0x10578b48 // mov rdx, qword [rdi + 16] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x04568966 // mov word [rsi + 4], dx + LONG $0x18578b48 // mov rdx, qword [rdi + 24] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x06568966 // mov word [rsi + 6], dx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x20c78348 // add rdi, 32 + LONG $0x08c68348 // add rsi, 8 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB31_5 + +LBB31_1: + WORD $0xd285 // test edx, edx + JLE LBB31_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB31_3: + LONG $0x87048b4a // mov rax, qword [rdi + 4*r8] + LONG $0x8104b70f // movzx eax, word [rcx + 4*rax] + LONG $0x04894266; BYTE $0x06 // mov word [rsi + r8], ax + LONG $0x02c08349 // add r8, 2 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB31_3 + +LBB31_4: + RET + +TEXT ·_transpose_uint8_uint32_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB32_1 + +LBB32_5: + WORD $0xd089 // mov eax, edx + WORD $0xb60f; BYTE $0x17 // movzx edx, byte [rdi] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x1689 // mov dword [rsi], edx + LONG $0x0157b60f // movzx edx, byte [rdi + 1] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x04 // mov dword [rsi + 4], edx + LONG $0x0257b60f // movzx edx, byte [rdi + 2] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x08 // mov dword [rsi + 8], edx + LONG $0x0357b60f // movzx edx, byte [rdi + 3] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x0c // mov dword [rsi + 12], edx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x04c78348 // add rdi, 4 + LONG $0x10c68348 // add rsi, 16 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB32_5 + +LBB32_1: + WORD $0xd285 // test edx, edx + JLE LBB32_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB32_3: + LONG $0x04b60f42; BYTE $0x07 // movzx eax, byte [rdi + r8] + WORD $0x048b; BYTE $0x81 // mov eax, dword [rcx + 4*rax] + LONG $0x86048942 // mov dword [rsi + 4*r8], eax + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB32_3 + +LBB32_4: + RET + +TEXT ·_transpose_int8_uint32_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB33_1 + +LBB33_5: + WORD $0xd089 // mov eax, edx + LONG $0x17be0f48 // movsx rdx, byte [rdi] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x1689 // mov dword [rsi], edx + LONG $0x57be0f48; BYTE $0x01 // movsx rdx, byte [rdi + 1] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x04 // mov dword [rsi + 4], edx + LONG $0x57be0f48; BYTE $0x02 // movsx rdx, byte [rdi + 2] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x08 // mov dword [rsi + 8], edx + LONG $0x57be0f48; BYTE $0x03 // movsx rdx, byte [rdi + 3] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x0c // mov dword [rsi + 12], edx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x04c78348 // add rdi, 4 + LONG $0x10c68348 // add rsi, 16 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB33_5 + +LBB33_1: + WORD $0xd285 // test edx, edx + JLE LBB33_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB33_3: + LONG $0x04be0f4a; BYTE $0x07 // movsx rax, byte [rdi + r8] + WORD $0x048b; BYTE $0x81 // mov eax, dword [rcx + 4*rax] + LONG $0x86048942 // mov dword [rsi + 4*r8], eax + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB33_3 + +LBB33_4: + RET + +TEXT ·_transpose_uint16_uint32_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB34_1 + +LBB34_5: + WORD $0xd089 // mov eax, edx + WORD $0xb70f; BYTE $0x17 // movzx edx, word [rdi] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x1689 // mov dword [rsi], edx + LONG $0x0257b70f // movzx edx, word [rdi + 2] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x04 // mov dword [rsi + 4], edx + LONG $0x0457b70f // movzx edx, word [rdi + 4] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x08 // mov dword [rsi + 8], edx + LONG $0x0657b70f // movzx edx, word [rdi + 6] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x0c // mov dword [rsi + 12], edx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x08c78348 // add rdi, 8 + LONG $0x10c68348 // add rsi, 16 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB34_5 + +LBB34_1: + WORD $0xd285 // test edx, edx + JLE LBB34_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB34_3: + LONG $0x04b70f42; BYTE $0x07 // movzx eax, word [rdi + r8] + WORD $0x048b; BYTE $0x81 // mov eax, dword [rcx + 4*rax] + LONG $0x46048942 // mov dword [rsi + 2*r8], eax + LONG $0x02c08349 // add r8, 2 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB34_3 + +LBB34_4: + RET + +TEXT ·_transpose_int16_uint32_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB35_1 + +LBB35_5: + WORD $0xd089 // mov eax, edx + LONG $0x17bf0f48 // movsx rdx, word [rdi] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x1689 // mov dword [rsi], edx + LONG $0x57bf0f48; BYTE $0x02 // movsx rdx, word [rdi + 2] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x04 // mov dword [rsi + 4], edx + LONG $0x57bf0f48; BYTE $0x04 // movsx rdx, word [rdi + 4] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x08 // mov dword [rsi + 8], edx + LONG $0x57bf0f48; BYTE $0x06 // movsx rdx, word [rdi + 6] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x0c // mov dword [rsi + 12], edx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x08c78348 // add rdi, 8 + LONG $0x10c68348 // add rsi, 16 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB35_5 + +LBB35_1: + WORD $0xd285 // test edx, edx + JLE LBB35_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB35_3: + LONG $0x04bf0f4a; BYTE $0x07 // movsx rax, word [rdi + r8] + WORD $0x048b; BYTE $0x81 // mov eax, dword [rcx + 4*rax] + LONG $0x46048942 // mov dword [rsi + 2*r8], eax + LONG $0x02c08349 // add r8, 2 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB35_3 + +LBB35_4: + RET + +TEXT ·_transpose_uint32_uint32_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB36_1 + +LBB36_5: + WORD $0xd089 // mov eax, edx + WORD $0x178b // mov edx, dword [rdi] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x1689 // mov dword [rsi], edx + WORD $0x578b; BYTE $0x04 // mov edx, dword [rdi + 4] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x04 // mov dword [rsi + 4], edx + WORD $0x578b; BYTE $0x08 // mov edx, dword [rdi + 8] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x08 // mov dword [rsi + 8], edx + WORD $0x578b; BYTE $0x0c // mov edx, dword [rdi + 12] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x0c // mov dword [rsi + 12], edx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x10c78348 // add rdi, 16 + LONG $0x10c68348 // add rsi, 16 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB36_5 + +LBB36_1: + WORD $0xd285 // test edx, edx + JLE LBB36_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB36_3: + LONG $0x07048b42 // mov eax, dword [rdi + r8] + WORD $0x048b; BYTE $0x81 // mov eax, dword [rcx + 4*rax] + LONG $0x06048942 // mov dword [rsi + r8], eax + LONG $0x04c08349 // add r8, 4 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB36_3 + +LBB36_4: + RET + +TEXT ·_transpose_int32_uint32_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB37_1 + +LBB37_5: + WORD $0xd089 // mov eax, edx + WORD $0x6348; BYTE $0x17 // movsxd rdx, dword [rdi] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x1689 // mov dword [rsi], edx + LONG $0x04576348 // movsxd rdx, dword [rdi + 4] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x04 // mov dword [rsi + 4], edx + LONG $0x08576348 // movsxd rdx, dword [rdi + 8] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x08 // mov dword [rsi + 8], edx + LONG $0x0c576348 // movsxd rdx, dword [rdi + 12] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x0c // mov dword [rsi + 12], edx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x10c78348 // add rdi, 16 + LONG $0x10c68348 // add rsi, 16 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB37_5 + +LBB37_1: + WORD $0xd285 // test edx, edx + JLE LBB37_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB37_3: + LONG $0x0704634a // movsxd rax, dword [rdi + r8] + WORD $0x048b; BYTE $0x81 // mov eax, dword [rcx + 4*rax] + LONG $0x06048942 // mov dword [rsi + r8], eax + LONG $0x04c08349 // add r8, 4 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB37_3 + +LBB37_4: + RET + +TEXT ·_transpose_uint64_uint32_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB38_1 + +LBB38_5: + WORD $0xd089 // mov eax, edx + WORD $0x8b48; BYTE $0x17 // mov rdx, qword [rdi] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x1689 // mov dword [rsi], edx + LONG $0x08578b48 // mov rdx, qword [rdi + 8] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x04 // mov dword [rsi + 4], edx + LONG $0x10578b48 // mov rdx, qword [rdi + 16] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x08 // mov dword [rsi + 8], edx + LONG $0x18578b48 // mov rdx, qword [rdi + 24] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x0c // mov dword [rsi + 12], edx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x20c78348 // add rdi, 32 + LONG $0x10c68348 // add rsi, 16 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB38_5 + +LBB38_1: + WORD $0xd285 // test edx, edx + JLE LBB38_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB38_3: + LONG $0x47048b4a // mov rax, qword [rdi + 2*r8] + WORD $0x048b; BYTE $0x81 // mov eax, dword [rcx + 4*rax] + LONG $0x06048942 // mov dword [rsi + r8], eax + LONG $0x04c08349 // add r8, 4 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB38_3 + +LBB38_4: + RET + +TEXT ·_transpose_int64_uint32_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB39_1 + +LBB39_5: + WORD $0xd089 // mov eax, edx + WORD $0x8b48; BYTE $0x17 // mov rdx, qword [rdi] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x1689 // mov dword [rsi], edx + LONG $0x08578b48 // mov rdx, qword [rdi + 8] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x04 // mov dword [rsi + 4], edx + LONG $0x10578b48 // mov rdx, qword [rdi + 16] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x08 // mov dword [rsi + 8], edx + LONG $0x18578b48 // mov rdx, qword [rdi + 24] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x0c // mov dword [rsi + 12], edx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x20c78348 // add rdi, 32 + LONG $0x10c68348 // add rsi, 16 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB39_5 + +LBB39_1: + WORD $0xd285 // test edx, edx + JLE LBB39_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB39_3: + LONG $0x47048b4a // mov rax, qword [rdi + 2*r8] + WORD $0x048b; BYTE $0x81 // mov eax, dword [rcx + 4*rax] + LONG $0x06048942 // mov dword [rsi + r8], eax + LONG $0x04c08349 // add r8, 4 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB39_3 + +LBB39_4: + RET + +TEXT ·_transpose_uint8_int32_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB40_1 + +LBB40_5: + WORD $0xd089 // mov eax, edx + WORD $0xb60f; BYTE $0x17 // movzx edx, byte [rdi] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x1689 // mov dword [rsi], edx + LONG $0x0157b60f // movzx edx, byte [rdi + 1] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x04 // mov dword [rsi + 4], edx + LONG $0x0257b60f // movzx edx, byte [rdi + 2] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x08 // mov dword [rsi + 8], edx + LONG $0x0357b60f // movzx edx, byte [rdi + 3] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x0c // mov dword [rsi + 12], edx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x04c78348 // add rdi, 4 + LONG $0x10c68348 // add rsi, 16 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB40_5 + +LBB40_1: + WORD $0xd285 // test edx, edx + JLE LBB40_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB40_3: + LONG $0x04b60f42; BYTE $0x07 // movzx eax, byte [rdi + r8] + WORD $0x048b; BYTE $0x81 // mov eax, dword [rcx + 4*rax] + LONG $0x86048942 // mov dword [rsi + 4*r8], eax + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB40_3 + +LBB40_4: + RET + +TEXT ·_transpose_int8_int32_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB41_1 + +LBB41_5: + WORD $0xd089 // mov eax, edx + LONG $0x17be0f48 // movsx rdx, byte [rdi] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x1689 // mov dword [rsi], edx + LONG $0x57be0f48; BYTE $0x01 // movsx rdx, byte [rdi + 1] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x04 // mov dword [rsi + 4], edx + LONG $0x57be0f48; BYTE $0x02 // movsx rdx, byte [rdi + 2] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x08 // mov dword [rsi + 8], edx + LONG $0x57be0f48; BYTE $0x03 // movsx rdx, byte [rdi + 3] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x0c // mov dword [rsi + 12], edx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x04c78348 // add rdi, 4 + LONG $0x10c68348 // add rsi, 16 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB41_5 + +LBB41_1: + WORD $0xd285 // test edx, edx + JLE LBB41_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB41_3: + LONG $0x04be0f4a; BYTE $0x07 // movsx rax, byte [rdi + r8] + WORD $0x048b; BYTE $0x81 // mov eax, dword [rcx + 4*rax] + LONG $0x86048942 // mov dword [rsi + 4*r8], eax + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB41_3 + +LBB41_4: + RET + +TEXT ·_transpose_uint16_int32_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB42_1 + +LBB42_5: + WORD $0xd089 // mov eax, edx + WORD $0xb70f; BYTE $0x17 // movzx edx, word [rdi] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x1689 // mov dword [rsi], edx + LONG $0x0257b70f // movzx edx, word [rdi + 2] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x04 // mov dword [rsi + 4], edx + LONG $0x0457b70f // movzx edx, word [rdi + 4] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x08 // mov dword [rsi + 8], edx + LONG $0x0657b70f // movzx edx, word [rdi + 6] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x0c // mov dword [rsi + 12], edx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x08c78348 // add rdi, 8 + LONG $0x10c68348 // add rsi, 16 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB42_5 + +LBB42_1: + WORD $0xd285 // test edx, edx + JLE LBB42_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB42_3: + LONG $0x04b70f42; BYTE $0x07 // movzx eax, word [rdi + r8] + WORD $0x048b; BYTE $0x81 // mov eax, dword [rcx + 4*rax] + LONG $0x46048942 // mov dword [rsi + 2*r8], eax + LONG $0x02c08349 // add r8, 2 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB42_3 + +LBB42_4: + RET + +TEXT ·_transpose_int16_int32_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB43_1 + +LBB43_5: + WORD $0xd089 // mov eax, edx + LONG $0x17bf0f48 // movsx rdx, word [rdi] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x1689 // mov dword [rsi], edx + LONG $0x57bf0f48; BYTE $0x02 // movsx rdx, word [rdi + 2] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x04 // mov dword [rsi + 4], edx + LONG $0x57bf0f48; BYTE $0x04 // movsx rdx, word [rdi + 4] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x08 // mov dword [rsi + 8], edx + LONG $0x57bf0f48; BYTE $0x06 // movsx rdx, word [rdi + 6] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x0c // mov dword [rsi + 12], edx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x08c78348 // add rdi, 8 + LONG $0x10c68348 // add rsi, 16 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB43_5 + +LBB43_1: + WORD $0xd285 // test edx, edx + JLE LBB43_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB43_3: + LONG $0x04bf0f4a; BYTE $0x07 // movsx rax, word [rdi + r8] + WORD $0x048b; BYTE $0x81 // mov eax, dword [rcx + 4*rax] + LONG $0x46048942 // mov dword [rsi + 2*r8], eax + LONG $0x02c08349 // add r8, 2 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB43_3 + +LBB43_4: + RET + +TEXT ·_transpose_uint32_int32_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB44_1 + +LBB44_5: + WORD $0xd089 // mov eax, edx + WORD $0x178b // mov edx, dword [rdi] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x1689 // mov dword [rsi], edx + WORD $0x578b; BYTE $0x04 // mov edx, dword [rdi + 4] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x04 // mov dword [rsi + 4], edx + WORD $0x578b; BYTE $0x08 // mov edx, dword [rdi + 8] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x08 // mov dword [rsi + 8], edx + WORD $0x578b; BYTE $0x0c // mov edx, dword [rdi + 12] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x0c // mov dword [rsi + 12], edx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x10c78348 // add rdi, 16 + LONG $0x10c68348 // add rsi, 16 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB44_5 + +LBB44_1: + WORD $0xd285 // test edx, edx + JLE LBB44_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB44_3: + LONG $0x07048b42 // mov eax, dword [rdi + r8] + WORD $0x048b; BYTE $0x81 // mov eax, dword [rcx + 4*rax] + LONG $0x06048942 // mov dword [rsi + r8], eax + LONG $0x04c08349 // add r8, 4 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB44_3 + +LBB44_4: + RET + +TEXT ·_transpose_int32_int32_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB45_1 + +LBB45_5: + WORD $0xd089 // mov eax, edx + WORD $0x6348; BYTE $0x17 // movsxd rdx, dword [rdi] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x1689 // mov dword [rsi], edx + LONG $0x04576348 // movsxd rdx, dword [rdi + 4] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x04 // mov dword [rsi + 4], edx + LONG $0x08576348 // movsxd rdx, dword [rdi + 8] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x08 // mov dword [rsi + 8], edx + LONG $0x0c576348 // movsxd rdx, dword [rdi + 12] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x0c // mov dword [rsi + 12], edx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x10c78348 // add rdi, 16 + LONG $0x10c68348 // add rsi, 16 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB45_5 + +LBB45_1: + WORD $0xd285 // test edx, edx + JLE LBB45_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB45_3: + LONG $0x0704634a // movsxd rax, dword [rdi + r8] + WORD $0x048b; BYTE $0x81 // mov eax, dword [rcx + 4*rax] + LONG $0x06048942 // mov dword [rsi + r8], eax + LONG $0x04c08349 // add r8, 4 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB45_3 + +LBB45_4: + RET + +TEXT ·_transpose_uint64_int32_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB46_1 + +LBB46_5: + WORD $0xd089 // mov eax, edx + WORD $0x8b48; BYTE $0x17 // mov rdx, qword [rdi] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x1689 // mov dword [rsi], edx + LONG $0x08578b48 // mov rdx, qword [rdi + 8] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x04 // mov dword [rsi + 4], edx + LONG $0x10578b48 // mov rdx, qword [rdi + 16] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x08 // mov dword [rsi + 8], edx + LONG $0x18578b48 // mov rdx, qword [rdi + 24] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x0c // mov dword [rsi + 12], edx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x20c78348 // add rdi, 32 + LONG $0x10c68348 // add rsi, 16 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB46_5 + +LBB46_1: + WORD $0xd285 // test edx, edx + JLE LBB46_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB46_3: + LONG $0x47048b4a // mov rax, qword [rdi + 2*r8] + WORD $0x048b; BYTE $0x81 // mov eax, dword [rcx + 4*rax] + LONG $0x06048942 // mov dword [rsi + r8], eax + LONG $0x04c08349 // add r8, 4 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB46_3 + +LBB46_4: + RET + +TEXT ·_transpose_int64_int32_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB47_1 + +LBB47_5: + WORD $0xd089 // mov eax, edx + WORD $0x8b48; BYTE $0x17 // mov rdx, qword [rdi] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x1689 // mov dword [rsi], edx + LONG $0x08578b48 // mov rdx, qword [rdi + 8] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x04 // mov dword [rsi + 4], edx + LONG $0x10578b48 // mov rdx, qword [rdi + 16] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x08 // mov dword [rsi + 8], edx + LONG $0x18578b48 // mov rdx, qword [rdi + 24] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x0c // mov dword [rsi + 12], edx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x20c78348 // add rdi, 32 + LONG $0x10c68348 // add rsi, 16 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB47_5 + +LBB47_1: + WORD $0xd285 // test edx, edx + JLE LBB47_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB47_3: + LONG $0x47048b4a // mov rax, qword [rdi + 2*r8] + WORD $0x048b; BYTE $0x81 // mov eax, dword [rcx + 4*rax] + LONG $0x06048942 // mov dword [rsi + r8], eax + LONG $0x04c08349 // add r8, 4 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB47_3 + +LBB47_4: + RET + +TEXT ·_transpose_uint8_uint64_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB48_1 + +LBB48_5: + WORD $0xd089 // mov eax, edx + WORD $0xb60f; BYTE $0x17 // movzx edx, byte [rdi] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + WORD $0x8948; BYTE $0x16 // mov qword [rsi], rdx + LONG $0x0157b60f // movzx edx, byte [rdi + 1] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x08568948 // mov qword [rsi + 8], rdx + LONG $0x0257b60f // movzx edx, byte [rdi + 2] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x10568948 // mov qword [rsi + 16], rdx + LONG $0x0357b60f // movzx edx, byte [rdi + 3] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x18568948 // mov qword [rsi + 24], rdx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x04c78348 // add rdi, 4 + LONG $0x20c68348 // add rsi, 32 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB48_5 + +LBB48_1: + WORD $0xd285 // test edx, edx + JLE LBB48_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB48_3: + LONG $0x04b60f42; BYTE $0x07 // movzx eax, byte [rdi + r8] + LONG $0x81046348 // movsxd rax, dword [rcx + 4*rax] + LONG $0xc604894a // mov qword [rsi + 8*r8], rax + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB48_3 + +LBB48_4: + RET + +TEXT ·_transpose_int8_uint64_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB49_1 + +LBB49_5: + WORD $0xd089 // mov eax, edx + LONG $0x17be0f48 // movsx rdx, byte [rdi] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + WORD $0x8948; BYTE $0x16 // mov qword [rsi], rdx + LONG $0x57be0f48; BYTE $0x01 // movsx rdx, byte [rdi + 1] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x08568948 // mov qword [rsi + 8], rdx + LONG $0x57be0f48; BYTE $0x02 // movsx rdx, byte [rdi + 2] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x10568948 // mov qword [rsi + 16], rdx + LONG $0x57be0f48; BYTE $0x03 // movsx rdx, byte [rdi + 3] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x18568948 // mov qword [rsi + 24], rdx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x04c78348 // add rdi, 4 + LONG $0x20c68348 // add rsi, 32 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB49_5 + +LBB49_1: + WORD $0xd285 // test edx, edx + JLE LBB49_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB49_3: + LONG $0x04be0f4a; BYTE $0x07 // movsx rax, byte [rdi + r8] + LONG $0x81046348 // movsxd rax, dword [rcx + 4*rax] + LONG $0xc604894a // mov qword [rsi + 8*r8], rax + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB49_3 + +LBB49_4: + RET + +TEXT ·_transpose_uint16_uint64_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB50_1 + +LBB50_5: + WORD $0xd089 // mov eax, edx + WORD $0xb70f; BYTE $0x17 // movzx edx, word [rdi] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + WORD $0x8948; BYTE $0x16 // mov qword [rsi], rdx + LONG $0x0257b70f // movzx edx, word [rdi + 2] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x08568948 // mov qword [rsi + 8], rdx + LONG $0x0457b70f // movzx edx, word [rdi + 4] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x10568948 // mov qword [rsi + 16], rdx + LONG $0x0657b70f // movzx edx, word [rdi + 6] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x18568948 // mov qword [rsi + 24], rdx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x08c78348 // add rdi, 8 + LONG $0x20c68348 // add rsi, 32 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB50_5 + +LBB50_1: + WORD $0xd285 // test edx, edx + JLE LBB50_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB50_3: + LONG $0x04b70f42; BYTE $0x07 // movzx eax, word [rdi + r8] + LONG $0x81046348 // movsxd rax, dword [rcx + 4*rax] + LONG $0x8604894a // mov qword [rsi + 4*r8], rax + LONG $0x02c08349 // add r8, 2 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB50_3 + +LBB50_4: + RET + +TEXT ·_transpose_int16_uint64_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB51_1 + +LBB51_5: + WORD $0xd089 // mov eax, edx + LONG $0x17bf0f48 // movsx rdx, word [rdi] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + WORD $0x8948; BYTE $0x16 // mov qword [rsi], rdx + LONG $0x57bf0f48; BYTE $0x02 // movsx rdx, word [rdi + 2] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x08568948 // mov qword [rsi + 8], rdx + LONG $0x57bf0f48; BYTE $0x04 // movsx rdx, word [rdi + 4] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x10568948 // mov qword [rsi + 16], rdx + LONG $0x57bf0f48; BYTE $0x06 // movsx rdx, word [rdi + 6] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x18568948 // mov qword [rsi + 24], rdx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x08c78348 // add rdi, 8 + LONG $0x20c68348 // add rsi, 32 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB51_5 + +LBB51_1: + WORD $0xd285 // test edx, edx + JLE LBB51_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB51_3: + LONG $0x04bf0f4a; BYTE $0x07 // movsx rax, word [rdi + r8] + LONG $0x81046348 // movsxd rax, dword [rcx + 4*rax] + LONG $0x8604894a // mov qword [rsi + 4*r8], rax + LONG $0x02c08349 // add r8, 2 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB51_3 + +LBB51_4: + RET + +TEXT ·_transpose_uint32_uint64_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB52_1 + +LBB52_5: + WORD $0xd089 // mov eax, edx + WORD $0x178b // mov edx, dword [rdi] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + WORD $0x8948; BYTE $0x16 // mov qword [rsi], rdx + WORD $0x578b; BYTE $0x04 // mov edx, dword [rdi + 4] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x08568948 // mov qword [rsi + 8], rdx + WORD $0x578b; BYTE $0x08 // mov edx, dword [rdi + 8] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x10568948 // mov qword [rsi + 16], rdx + WORD $0x578b; BYTE $0x0c // mov edx, dword [rdi + 12] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x18568948 // mov qword [rsi + 24], rdx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x10c78348 // add rdi, 16 + LONG $0x20c68348 // add rsi, 32 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB52_5 + +LBB52_1: + WORD $0xd285 // test edx, edx + JLE LBB52_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB52_3: + LONG $0x07048b42 // mov eax, dword [rdi + r8] + LONG $0x81046348 // movsxd rax, dword [rcx + 4*rax] + LONG $0x4604894a // mov qword [rsi + 2*r8], rax + LONG $0x04c08349 // add r8, 4 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB52_3 + +LBB52_4: + RET + +TEXT ·_transpose_int32_uint64_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB53_1 + +LBB53_5: + WORD $0xd089 // mov eax, edx + WORD $0x6348; BYTE $0x17 // movsxd rdx, dword [rdi] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + WORD $0x8948; BYTE $0x16 // mov qword [rsi], rdx + LONG $0x04576348 // movsxd rdx, dword [rdi + 4] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x08568948 // mov qword [rsi + 8], rdx + LONG $0x08576348 // movsxd rdx, dword [rdi + 8] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x10568948 // mov qword [rsi + 16], rdx + LONG $0x0c576348 // movsxd rdx, dword [rdi + 12] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x18568948 // mov qword [rsi + 24], rdx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x10c78348 // add rdi, 16 + LONG $0x20c68348 // add rsi, 32 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB53_5 + +LBB53_1: + WORD $0xd285 // test edx, edx + JLE LBB53_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB53_3: + LONG $0x0704634a // movsxd rax, dword [rdi + r8] + LONG $0x81046348 // movsxd rax, dword [rcx + 4*rax] + LONG $0x4604894a // mov qword [rsi + 2*r8], rax + LONG $0x04c08349 // add r8, 4 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB53_3 + +LBB53_4: + RET + +TEXT ·_transpose_uint64_uint64_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB54_1 + +LBB54_5: + WORD $0xd089 // mov eax, edx + WORD $0x8b48; BYTE $0x17 // mov rdx, qword [rdi] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + WORD $0x8948; BYTE $0x16 // mov qword [rsi], rdx + LONG $0x08578b48 // mov rdx, qword [rdi + 8] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x08568948 // mov qword [rsi + 8], rdx + LONG $0x10578b48 // mov rdx, qword [rdi + 16] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x10568948 // mov qword [rsi + 16], rdx + LONG $0x18578b48 // mov rdx, qword [rdi + 24] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x18568948 // mov qword [rsi + 24], rdx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x20c78348 // add rdi, 32 + LONG $0x20c68348 // add rsi, 32 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB54_5 + +LBB54_1: + WORD $0xd285 // test edx, edx + JLE LBB54_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB54_3: + LONG $0x07048b4a // mov rax, qword [rdi + r8] + LONG $0x81046348 // movsxd rax, dword [rcx + 4*rax] + LONG $0x0604894a // mov qword [rsi + r8], rax + LONG $0x08c08349 // add r8, 8 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB54_3 + +LBB54_4: + RET + +TEXT ·_transpose_int64_uint64_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB55_1 + +LBB55_5: + WORD $0xd089 // mov eax, edx + WORD $0x8b48; BYTE $0x17 // mov rdx, qword [rdi] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + WORD $0x8948; BYTE $0x16 // mov qword [rsi], rdx + LONG $0x08578b48 // mov rdx, qword [rdi + 8] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x08568948 // mov qword [rsi + 8], rdx + LONG $0x10578b48 // mov rdx, qword [rdi + 16] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x10568948 // mov qword [rsi + 16], rdx + LONG $0x18578b48 // mov rdx, qword [rdi + 24] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x18568948 // mov qword [rsi + 24], rdx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x20c78348 // add rdi, 32 + LONG $0x20c68348 // add rsi, 32 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB55_5 + +LBB55_1: + WORD $0xd285 // test edx, edx + JLE LBB55_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB55_3: + LONG $0x07048b4a // mov rax, qword [rdi + r8] + LONG $0x81046348 // movsxd rax, dword [rcx + 4*rax] + LONG $0x0604894a // mov qword [rsi + r8], rax + LONG $0x08c08349 // add r8, 8 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB55_3 + +LBB55_4: + RET + +TEXT ·_transpose_uint8_int64_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB56_1 + +LBB56_5: + WORD $0xd089 // mov eax, edx + WORD $0xb60f; BYTE $0x17 // movzx edx, byte [rdi] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + WORD $0x8948; BYTE $0x16 // mov qword [rsi], rdx + LONG $0x0157b60f // movzx edx, byte [rdi + 1] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x08568948 // mov qword [rsi + 8], rdx + LONG $0x0257b60f // movzx edx, byte [rdi + 2] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x10568948 // mov qword [rsi + 16], rdx + LONG $0x0357b60f // movzx edx, byte [rdi + 3] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x18568948 // mov qword [rsi + 24], rdx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x04c78348 // add rdi, 4 + LONG $0x20c68348 // add rsi, 32 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB56_5 + +LBB56_1: + WORD $0xd285 // test edx, edx + JLE LBB56_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB56_3: + LONG $0x04b60f42; BYTE $0x07 // movzx eax, byte [rdi + r8] + LONG $0x81046348 // movsxd rax, dword [rcx + 4*rax] + LONG $0xc604894a // mov qword [rsi + 8*r8], rax + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB56_3 + +LBB56_4: + RET + +TEXT ·_transpose_int8_int64_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB57_1 + +LBB57_5: + WORD $0xd089 // mov eax, edx + LONG $0x17be0f48 // movsx rdx, byte [rdi] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + WORD $0x8948; BYTE $0x16 // mov qword [rsi], rdx + LONG $0x57be0f48; BYTE $0x01 // movsx rdx, byte [rdi + 1] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x08568948 // mov qword [rsi + 8], rdx + LONG $0x57be0f48; BYTE $0x02 // movsx rdx, byte [rdi + 2] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x10568948 // mov qword [rsi + 16], rdx + LONG $0x57be0f48; BYTE $0x03 // movsx rdx, byte [rdi + 3] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x18568948 // mov qword [rsi + 24], rdx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x04c78348 // add rdi, 4 + LONG $0x20c68348 // add rsi, 32 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB57_5 + +LBB57_1: + WORD $0xd285 // test edx, edx + JLE LBB57_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB57_3: + LONG $0x04be0f4a; BYTE $0x07 // movsx rax, byte [rdi + r8] + LONG $0x81046348 // movsxd rax, dword [rcx + 4*rax] + LONG $0xc604894a // mov qword [rsi + 8*r8], rax + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB57_3 + +LBB57_4: + RET + +TEXT ·_transpose_uint16_int64_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB58_1 + +LBB58_5: + WORD $0xd089 // mov eax, edx + WORD $0xb70f; BYTE $0x17 // movzx edx, word [rdi] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + WORD $0x8948; BYTE $0x16 // mov qword [rsi], rdx + LONG $0x0257b70f // movzx edx, word [rdi + 2] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x08568948 // mov qword [rsi + 8], rdx + LONG $0x0457b70f // movzx edx, word [rdi + 4] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x10568948 // mov qword [rsi + 16], rdx + LONG $0x0657b70f // movzx edx, word [rdi + 6] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x18568948 // mov qword [rsi + 24], rdx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x08c78348 // add rdi, 8 + LONG $0x20c68348 // add rsi, 32 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB58_5 + +LBB58_1: + WORD $0xd285 // test edx, edx + JLE LBB58_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB58_3: + LONG $0x04b70f42; BYTE $0x07 // movzx eax, word [rdi + r8] + LONG $0x81046348 // movsxd rax, dword [rcx + 4*rax] + LONG $0x8604894a // mov qword [rsi + 4*r8], rax + LONG $0x02c08349 // add r8, 2 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB58_3 + +LBB58_4: + RET + +TEXT ·_transpose_int16_int64_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB59_1 + +LBB59_5: + WORD $0xd089 // mov eax, edx + LONG $0x17bf0f48 // movsx rdx, word [rdi] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + WORD $0x8948; BYTE $0x16 // mov qword [rsi], rdx + LONG $0x57bf0f48; BYTE $0x02 // movsx rdx, word [rdi + 2] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x08568948 // mov qword [rsi + 8], rdx + LONG $0x57bf0f48; BYTE $0x04 // movsx rdx, word [rdi + 4] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x10568948 // mov qword [rsi + 16], rdx + LONG $0x57bf0f48; BYTE $0x06 // movsx rdx, word [rdi + 6] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x18568948 // mov qword [rsi + 24], rdx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x08c78348 // add rdi, 8 + LONG $0x20c68348 // add rsi, 32 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB59_5 + +LBB59_1: + WORD $0xd285 // test edx, edx + JLE LBB59_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB59_3: + LONG $0x04bf0f4a; BYTE $0x07 // movsx rax, word [rdi + r8] + LONG $0x81046348 // movsxd rax, dword [rcx + 4*rax] + LONG $0x8604894a // mov qword [rsi + 4*r8], rax + LONG $0x02c08349 // add r8, 2 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB59_3 + +LBB59_4: + RET + +TEXT ·_transpose_uint32_int64_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB60_1 + +LBB60_5: + WORD $0xd089 // mov eax, edx + WORD $0x178b // mov edx, dword [rdi] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + WORD $0x8948; BYTE $0x16 // mov qword [rsi], rdx + WORD $0x578b; BYTE $0x04 // mov edx, dword [rdi + 4] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x08568948 // mov qword [rsi + 8], rdx + WORD $0x578b; BYTE $0x08 // mov edx, dword [rdi + 8] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x10568948 // mov qword [rsi + 16], rdx + WORD $0x578b; BYTE $0x0c // mov edx, dword [rdi + 12] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x18568948 // mov qword [rsi + 24], rdx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x10c78348 // add rdi, 16 + LONG $0x20c68348 // add rsi, 32 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB60_5 + +LBB60_1: + WORD $0xd285 // test edx, edx + JLE LBB60_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB60_3: + LONG $0x07048b42 // mov eax, dword [rdi + r8] + LONG $0x81046348 // movsxd rax, dword [rcx + 4*rax] + LONG $0x4604894a // mov qword [rsi + 2*r8], rax + LONG $0x04c08349 // add r8, 4 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB60_3 + +LBB60_4: + RET + +TEXT ·_transpose_int32_int64_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB61_1 + +LBB61_5: + WORD $0xd089 // mov eax, edx + WORD $0x6348; BYTE $0x17 // movsxd rdx, dword [rdi] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + WORD $0x8948; BYTE $0x16 // mov qword [rsi], rdx + LONG $0x04576348 // movsxd rdx, dword [rdi + 4] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x08568948 // mov qword [rsi + 8], rdx + LONG $0x08576348 // movsxd rdx, dword [rdi + 8] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x10568948 // mov qword [rsi + 16], rdx + LONG $0x0c576348 // movsxd rdx, dword [rdi + 12] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x18568948 // mov qword [rsi + 24], rdx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x10c78348 // add rdi, 16 + LONG $0x20c68348 // add rsi, 32 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB61_5 + +LBB61_1: + WORD $0xd285 // test edx, edx + JLE LBB61_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB61_3: + LONG $0x0704634a // movsxd rax, dword [rdi + r8] + LONG $0x81046348 // movsxd rax, dword [rcx + 4*rax] + LONG $0x4604894a // mov qword [rsi + 2*r8], rax + LONG $0x04c08349 // add r8, 4 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB61_3 + +LBB61_4: + RET + +TEXT ·_transpose_uint64_int64_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB62_1 + +LBB62_5: + WORD $0xd089 // mov eax, edx + WORD $0x8b48; BYTE $0x17 // mov rdx, qword [rdi] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + WORD $0x8948; BYTE $0x16 // mov qword [rsi], rdx + LONG $0x08578b48 // mov rdx, qword [rdi + 8] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x08568948 // mov qword [rsi + 8], rdx + LONG $0x10578b48 // mov rdx, qword [rdi + 16] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x10568948 // mov qword [rsi + 16], rdx + LONG $0x18578b48 // mov rdx, qword [rdi + 24] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x18568948 // mov qword [rsi + 24], rdx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x20c78348 // add rdi, 32 + LONG $0x20c68348 // add rsi, 32 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB62_5 + +LBB62_1: + WORD $0xd285 // test edx, edx + JLE LBB62_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB62_3: + LONG $0x07048b4a // mov rax, qword [rdi + r8] + LONG $0x81046348 // movsxd rax, dword [rcx + 4*rax] + LONG $0x0604894a // mov qword [rsi + r8], rax + LONG $0x08c08349 // add r8, 8 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB62_3 + +LBB62_4: + RET + +TEXT ·_transpose_int64_int64_avx2(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB63_1 + +LBB63_5: + WORD $0xd089 // mov eax, edx + WORD $0x8b48; BYTE $0x17 // mov rdx, qword [rdi] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + WORD $0x8948; BYTE $0x16 // mov qword [rsi], rdx + LONG $0x08578b48 // mov rdx, qword [rdi + 8] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x08568948 // mov qword [rsi + 8], rdx + LONG $0x10578b48 // mov rdx, qword [rdi + 16] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x10568948 // mov qword [rsi + 16], rdx + LONG $0x18578b48 // mov rdx, qword [rdi + 24] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x18568948 // mov qword [rsi + 24], rdx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x20c78348 // add rdi, 32 + LONG $0x20c68348 // add rsi, 32 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB63_5 + +LBB63_1: + WORD $0xd285 // test edx, edx + JLE LBB63_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB63_3: + LONG $0x07048b4a // mov rax, qword [rdi + r8] + LONG $0x81046348 // movsxd rax, dword [rcx + 4*rax] + LONG $0x0604894a // mov qword [rsi + r8], rax + LONG $0x08c08349 // add r8, 8 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB63_3 + +LBB63_4: + RET diff --git a/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_def.go b/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_def.go new file mode 100644 index 000000000..cc3b0abb5 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_def.go @@ -0,0 +1,227 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package utils + +import ( + "errors" + + "github.com/apache/arrow/go/v14/arrow" +) + +//go:generate go run ../../arrow/_tools/tmpl -i -data=transpose_ints.tmpldata -d arch=avx2 transpose_ints_simd.go.tmpl=transpose_ints_avx2_amd64.go +//go:generate go run ../../arrow/_tools/tmpl -i -data=transpose_ints.tmpldata -d arch=sse4 transpose_ints_simd.go.tmpl=transpose_ints_sse4_amd64.go +//go:generate go run ../../arrow/_tools/tmpl -i -data=transpose_ints.tmpldata transpose_ints_s390x.go.tmpl=transpose_ints_s390x.go +//go:generate go run ../../arrow/_tools/tmpl -i -data=transpose_ints.tmpldata transpose_ints_s390x.go.tmpl=transpose_ints_arm64.go +//go:generate go run ../../arrow/_tools/tmpl -i -data=transpose_ints.tmpldata transpose_ints_noasm.go.tmpl=transpose_ints_noasm.go +//go:generate go run ../../arrow/_tools/tmpl -i -data=transpose_ints.tmpldata transpose_ints.go.tmpl=transpose_ints.go + +func bufToTyped(typ arrow.DataType, buf []byte, offset, length int) (interface{}, error) { + switch typ.ID() { + case arrow.INT8: + return arrow.Int8Traits.CastFromBytes(buf)[offset : offset+length], nil + case arrow.INT16: + return arrow.Int16Traits.CastFromBytes(buf)[offset : offset+length], nil + case arrow.INT32: + return arrow.Int32Traits.CastFromBytes(buf)[offset : offset+length], nil + case arrow.INT64: + return arrow.Int64Traits.CastFromBytes(buf)[offset : offset+length], nil + case arrow.UINT8: + return arrow.Uint8Traits.CastFromBytes(buf)[offset : offset+length], nil + case arrow.UINT16: + return arrow.Uint16Traits.CastFromBytes(buf)[offset : offset+length], nil + case arrow.UINT32: + return arrow.Uint32Traits.CastFromBytes(buf)[offset : offset+length], nil + case arrow.UINT64: + return arrow.Uint64Traits.CastFromBytes(buf)[offset : offset+length], nil + } + return nil, errors.New("only accepts integral types") +} + +// TransposeIntsBuffers takes the data-types, byte buffers, and offsets of a source and destination +// buffer to perform TransposeInts on with the provided mapping data. +func TransposeIntsBuffers(inType, outType arrow.DataType, indata, outdata []byte, inOffset, outOffset int, length int, transposeMap []int32) error { + src, err := bufToTyped(inType, indata, inOffset, length) + if err != nil { + return err + } + dest, err := bufToTyped(outType, outdata, outOffset, length) + if err != nil { + return err + } + + return TransposeInts(src, dest, transposeMap) +} + +// TransposeInts expects two integral slices and the values they map to. Returning +// an error if either src or dest are not an integral type. +func TransposeInts(src, dest interface{}, mapping []int32) error { + switch s := src.(type) { + case []int8: + switch d := dest.(type) { + case []int8: + TransposeInt8Int8(s, d, mapping) + case []int16: + TransposeInt8Int16(s, d, mapping) + case []int32: + TransposeInt8Int32(s, d, mapping) + case []int64: + TransposeInt8Int64(s, d, mapping) + case []uint8: + TransposeInt8Uint8(s, d, mapping) + case []uint16: + TransposeInt8Uint16(s, d, mapping) + case []uint32: + TransposeInt8Uint32(s, d, mapping) + case []uint64: + TransposeInt8Uint64(s, d, mapping) + } + case []int16: + switch d := dest.(type) { + case []int8: + TransposeInt16Int8(s, d, mapping) + case []int16: + TransposeInt16Int16(s, d, mapping) + case []int32: + TransposeInt16Int32(s, d, mapping) + case []int64: + TransposeInt16Int64(s, d, mapping) + case []uint8: + TransposeInt16Uint8(s, d, mapping) + case []uint16: + TransposeInt16Uint16(s, d, mapping) + case []uint32: + TransposeInt16Uint32(s, d, mapping) + case []uint64: + TransposeInt16Uint64(s, d, mapping) + } + case []int32: + switch d := dest.(type) { + case []int8: + TransposeInt32Int8(s, d, mapping) + case []int16: + TransposeInt32Int16(s, d, mapping) + case []int32: + TransposeInt32Int32(s, d, mapping) + case []int64: + TransposeInt32Int64(s, d, mapping) + case []uint8: + TransposeInt32Uint8(s, d, mapping) + case []uint16: + TransposeInt32Uint16(s, d, mapping) + case []uint32: + TransposeInt32Uint32(s, d, mapping) + case []uint64: + TransposeInt32Uint64(s, d, mapping) + } + case []int64: + switch d := dest.(type) { + case []int8: + TransposeInt64Int8(s, d, mapping) + case []int16: + TransposeInt64Int16(s, d, mapping) + case []int32: + TransposeInt64Int32(s, d, mapping) + case []int64: + TransposeInt64Int64(s, d, mapping) + case []uint8: + TransposeInt64Uint8(s, d, mapping) + case []uint16: + TransposeInt64Uint16(s, d, mapping) + case []uint32: + TransposeInt64Uint32(s, d, mapping) + case []uint64: + TransposeInt64Uint64(s, d, mapping) + } + case []uint8: + switch d := dest.(type) { + case []int8: + TransposeUint8Int8(s, d, mapping) + case []int16: + TransposeUint8Int16(s, d, mapping) + case []int32: + TransposeUint8Int32(s, d, mapping) + case []int64: + TransposeUint8Int64(s, d, mapping) + case []uint8: + TransposeUint8Uint8(s, d, mapping) + case []uint16: + TransposeUint8Uint16(s, d, mapping) + case []uint32: + TransposeUint8Uint32(s, d, mapping) + case []uint64: + TransposeUint8Uint64(s, d, mapping) + } + case []uint16: + switch d := dest.(type) { + case []int8: + TransposeUint16Int8(s, d, mapping) + case []int16: + TransposeUint16Int16(s, d, mapping) + case []int32: + TransposeUint16Int32(s, d, mapping) + case []int64: + TransposeUint16Int64(s, d, mapping) + case []uint8: + TransposeUint16Uint8(s, d, mapping) + case []uint16: + TransposeUint16Uint16(s, d, mapping) + case []uint32: + TransposeUint16Uint32(s, d, mapping) + case []uint64: + TransposeUint16Uint64(s, d, mapping) + } + case []uint32: + switch d := dest.(type) { + case []int8: + TransposeUint32Int8(s, d, mapping) + case []int16: + TransposeUint32Int16(s, d, mapping) + case []int32: + TransposeUint32Int32(s, d, mapping) + case []int64: + TransposeUint32Int64(s, d, mapping) + case []uint8: + TransposeUint32Uint8(s, d, mapping) + case []uint16: + TransposeUint32Uint16(s, d, mapping) + case []uint32: + TransposeUint32Uint32(s, d, mapping) + case []uint64: + TransposeUint32Uint64(s, d, mapping) + } + case []uint64: + switch d := dest.(type) { + case []int8: + TransposeUint64Int8(s, d, mapping) + case []int16: + TransposeUint64Int16(s, d, mapping) + case []int32: + TransposeUint64Int32(s, d, mapping) + case []int64: + TransposeUint64Int64(s, d, mapping) + case []uint8: + TransposeUint64Uint8(s, d, mapping) + case []uint16: + TransposeUint64Uint16(s, d, mapping) + case []uint32: + TransposeUint64Uint32(s, d, mapping) + case []uint64: + TransposeUint64Uint64(s, d, mapping) + } + } + return nil +} diff --git a/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_noasm.go b/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_noasm.go new file mode 100644 index 000000000..461aaf31f --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_noasm.go @@ -0,0 +1,96 @@ +// Code generated by transpose_ints_noasm.go.tmpl. DO NOT EDIT. + +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build noasm || (!amd64 && !arm64 && !s390x && !ppc64le) + +package utils + +// if building with the 'noasm' tag, then point to the pure go implementations +var ( + TransposeInt8Int8 = transposeInt8Int8 + TransposeInt8Uint8 = transposeInt8Uint8 + TransposeInt8Int16 = transposeInt8Int16 + TransposeInt8Uint16 = transposeInt8Uint16 + TransposeInt8Int32 = transposeInt8Int32 + TransposeInt8Uint32 = transposeInt8Uint32 + TransposeInt8Int64 = transposeInt8Int64 + TransposeInt8Uint64 = transposeInt8Uint64 + + TransposeUint8Int8 = transposeUint8Int8 + TransposeUint8Uint8 = transposeUint8Uint8 + TransposeUint8Int16 = transposeUint8Int16 + TransposeUint8Uint16 = transposeUint8Uint16 + TransposeUint8Int32 = transposeUint8Int32 + TransposeUint8Uint32 = transposeUint8Uint32 + TransposeUint8Int64 = transposeUint8Int64 + TransposeUint8Uint64 = transposeUint8Uint64 + + TransposeInt16Int8 = transposeInt16Int8 + TransposeInt16Uint8 = transposeInt16Uint8 + TransposeInt16Int16 = transposeInt16Int16 + TransposeInt16Uint16 = transposeInt16Uint16 + TransposeInt16Int32 = transposeInt16Int32 + TransposeInt16Uint32 = transposeInt16Uint32 + TransposeInt16Int64 = transposeInt16Int64 + TransposeInt16Uint64 = transposeInt16Uint64 + + TransposeUint16Int8 = transposeUint16Int8 + TransposeUint16Uint8 = transposeUint16Uint8 + TransposeUint16Int16 = transposeUint16Int16 + TransposeUint16Uint16 = transposeUint16Uint16 + TransposeUint16Int32 = transposeUint16Int32 + TransposeUint16Uint32 = transposeUint16Uint32 + TransposeUint16Int64 = transposeUint16Int64 + TransposeUint16Uint64 = transposeUint16Uint64 + + TransposeInt32Int8 = transposeInt32Int8 + TransposeInt32Uint8 = transposeInt32Uint8 + TransposeInt32Int16 = transposeInt32Int16 + TransposeInt32Uint16 = transposeInt32Uint16 + TransposeInt32Int32 = transposeInt32Int32 + TransposeInt32Uint32 = transposeInt32Uint32 + TransposeInt32Int64 = transposeInt32Int64 + TransposeInt32Uint64 = transposeInt32Uint64 + + TransposeUint32Int8 = transposeUint32Int8 + TransposeUint32Uint8 = transposeUint32Uint8 + TransposeUint32Int16 = transposeUint32Int16 + TransposeUint32Uint16 = transposeUint32Uint16 + TransposeUint32Int32 = transposeUint32Int32 + TransposeUint32Uint32 = transposeUint32Uint32 + TransposeUint32Int64 = transposeUint32Int64 + TransposeUint32Uint64 = transposeUint32Uint64 + + TransposeInt64Int8 = transposeInt64Int8 + TransposeInt64Uint8 = transposeInt64Uint8 + TransposeInt64Int16 = transposeInt64Int16 + TransposeInt64Uint16 = transposeInt64Uint16 + TransposeInt64Int32 = transposeInt64Int32 + TransposeInt64Uint32 = transposeInt64Uint32 + TransposeInt64Int64 = transposeInt64Int64 + TransposeInt64Uint64 = transposeInt64Uint64 + + TransposeUint64Int8 = transposeUint64Int8 + TransposeUint64Uint8 = transposeUint64Uint8 + TransposeUint64Int16 = transposeUint64Int16 + TransposeUint64Uint16 = transposeUint64Uint16 + TransposeUint64Int32 = transposeUint64Int32 + TransposeUint64Uint32 = transposeUint64Uint32 + TransposeUint64Int64 = transposeUint64Int64 + TransposeUint64Uint64 = transposeUint64Uint64 +) diff --git a/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_noasm.go.tmpl b/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_noasm.go.tmpl new file mode 100644 index 000000000..faffdce35 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_noasm.go.tmpl @@ -0,0 +1,34 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build noasm +// +build noasm + +package utils + +// if building with the 'noasm' tag, then point to the pure go implementations +var ( +{{ $typelist := .In }} +{{range .In}} +{{ $src := .Type -}} +{{ $srcName := .Name -}} +{{ range $typelist -}} +{{ $dest := .Type -}} +{{ $destName := .Name -}} + Transpose{{$srcName}}{{$destName}} = transpose{{$srcName}}{{$destName}} +{{end}} +{{end}} +) diff --git a/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_ppc64le.go b/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_ppc64le.go new file mode 100644 index 000000000..cc957cdaa --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_ppc64le.go @@ -0,0 +1,96 @@ +// Code generated by transpose_ints_s390x.go.tmpl. DO NOT EDIT. + +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !noasm + +package utils + +// if building with the 'noasm' tag, then point to the pure go implementations +var ( + TransposeInt8Int8 = transposeInt8Int8 + TransposeInt8Uint8 = transposeInt8Uint8 + TransposeInt8Int16 = transposeInt8Int16 + TransposeInt8Uint16 = transposeInt8Uint16 + TransposeInt8Int32 = transposeInt8Int32 + TransposeInt8Uint32 = transposeInt8Uint32 + TransposeInt8Int64 = transposeInt8Int64 + TransposeInt8Uint64 = transposeInt8Uint64 + + TransposeUint8Int8 = transposeUint8Int8 + TransposeUint8Uint8 = transposeUint8Uint8 + TransposeUint8Int16 = transposeUint8Int16 + TransposeUint8Uint16 = transposeUint8Uint16 + TransposeUint8Int32 = transposeUint8Int32 + TransposeUint8Uint32 = transposeUint8Uint32 + TransposeUint8Int64 = transposeUint8Int64 + TransposeUint8Uint64 = transposeUint8Uint64 + + TransposeInt16Int8 = transposeInt16Int8 + TransposeInt16Uint8 = transposeInt16Uint8 + TransposeInt16Int16 = transposeInt16Int16 + TransposeInt16Uint16 = transposeInt16Uint16 + TransposeInt16Int32 = transposeInt16Int32 + TransposeInt16Uint32 = transposeInt16Uint32 + TransposeInt16Int64 = transposeInt16Int64 + TransposeInt16Uint64 = transposeInt16Uint64 + + TransposeUint16Int8 = transposeUint16Int8 + TransposeUint16Uint8 = transposeUint16Uint8 + TransposeUint16Int16 = transposeUint16Int16 + TransposeUint16Uint16 = transposeUint16Uint16 + TransposeUint16Int32 = transposeUint16Int32 + TransposeUint16Uint32 = transposeUint16Uint32 + TransposeUint16Int64 = transposeUint16Int64 + TransposeUint16Uint64 = transposeUint16Uint64 + + TransposeInt32Int8 = transposeInt32Int8 + TransposeInt32Uint8 = transposeInt32Uint8 + TransposeInt32Int16 = transposeInt32Int16 + TransposeInt32Uint16 = transposeInt32Uint16 + TransposeInt32Int32 = transposeInt32Int32 + TransposeInt32Uint32 = transposeInt32Uint32 + TransposeInt32Int64 = transposeInt32Int64 + TransposeInt32Uint64 = transposeInt32Uint64 + + TransposeUint32Int8 = transposeUint32Int8 + TransposeUint32Uint8 = transposeUint32Uint8 + TransposeUint32Int16 = transposeUint32Int16 + TransposeUint32Uint16 = transposeUint32Uint16 + TransposeUint32Int32 = transposeUint32Int32 + TransposeUint32Uint32 = transposeUint32Uint32 + TransposeUint32Int64 = transposeUint32Int64 + TransposeUint32Uint64 = transposeUint32Uint64 + + TransposeInt64Int8 = transposeInt64Int8 + TransposeInt64Uint8 = transposeInt64Uint8 + TransposeInt64Int16 = transposeInt64Int16 + TransposeInt64Uint16 = transposeInt64Uint16 + TransposeInt64Int32 = transposeInt64Int32 + TransposeInt64Uint32 = transposeInt64Uint32 + TransposeInt64Int64 = transposeInt64Int64 + TransposeInt64Uint64 = transposeInt64Uint64 + + TransposeUint64Int8 = transposeUint64Int8 + TransposeUint64Uint8 = transposeUint64Uint8 + TransposeUint64Int16 = transposeUint64Int16 + TransposeUint64Uint16 = transposeUint64Uint16 + TransposeUint64Int32 = transposeUint64Int32 + TransposeUint64Uint32 = transposeUint64Uint32 + TransposeUint64Int64 = transposeUint64Int64 + TransposeUint64Uint64 = transposeUint64Uint64 +) diff --git a/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_s390x.go b/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_s390x.go new file mode 100644 index 000000000..cc957cdaa --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_s390x.go @@ -0,0 +1,96 @@ +// Code generated by transpose_ints_s390x.go.tmpl. DO NOT EDIT. + +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !noasm + +package utils + +// if building with the 'noasm' tag, then point to the pure go implementations +var ( + TransposeInt8Int8 = transposeInt8Int8 + TransposeInt8Uint8 = transposeInt8Uint8 + TransposeInt8Int16 = transposeInt8Int16 + TransposeInt8Uint16 = transposeInt8Uint16 + TransposeInt8Int32 = transposeInt8Int32 + TransposeInt8Uint32 = transposeInt8Uint32 + TransposeInt8Int64 = transposeInt8Int64 + TransposeInt8Uint64 = transposeInt8Uint64 + + TransposeUint8Int8 = transposeUint8Int8 + TransposeUint8Uint8 = transposeUint8Uint8 + TransposeUint8Int16 = transposeUint8Int16 + TransposeUint8Uint16 = transposeUint8Uint16 + TransposeUint8Int32 = transposeUint8Int32 + TransposeUint8Uint32 = transposeUint8Uint32 + TransposeUint8Int64 = transposeUint8Int64 + TransposeUint8Uint64 = transposeUint8Uint64 + + TransposeInt16Int8 = transposeInt16Int8 + TransposeInt16Uint8 = transposeInt16Uint8 + TransposeInt16Int16 = transposeInt16Int16 + TransposeInt16Uint16 = transposeInt16Uint16 + TransposeInt16Int32 = transposeInt16Int32 + TransposeInt16Uint32 = transposeInt16Uint32 + TransposeInt16Int64 = transposeInt16Int64 + TransposeInt16Uint64 = transposeInt16Uint64 + + TransposeUint16Int8 = transposeUint16Int8 + TransposeUint16Uint8 = transposeUint16Uint8 + TransposeUint16Int16 = transposeUint16Int16 + TransposeUint16Uint16 = transposeUint16Uint16 + TransposeUint16Int32 = transposeUint16Int32 + TransposeUint16Uint32 = transposeUint16Uint32 + TransposeUint16Int64 = transposeUint16Int64 + TransposeUint16Uint64 = transposeUint16Uint64 + + TransposeInt32Int8 = transposeInt32Int8 + TransposeInt32Uint8 = transposeInt32Uint8 + TransposeInt32Int16 = transposeInt32Int16 + TransposeInt32Uint16 = transposeInt32Uint16 + TransposeInt32Int32 = transposeInt32Int32 + TransposeInt32Uint32 = transposeInt32Uint32 + TransposeInt32Int64 = transposeInt32Int64 + TransposeInt32Uint64 = transposeInt32Uint64 + + TransposeUint32Int8 = transposeUint32Int8 + TransposeUint32Uint8 = transposeUint32Uint8 + TransposeUint32Int16 = transposeUint32Int16 + TransposeUint32Uint16 = transposeUint32Uint16 + TransposeUint32Int32 = transposeUint32Int32 + TransposeUint32Uint32 = transposeUint32Uint32 + TransposeUint32Int64 = transposeUint32Int64 + TransposeUint32Uint64 = transposeUint32Uint64 + + TransposeInt64Int8 = transposeInt64Int8 + TransposeInt64Uint8 = transposeInt64Uint8 + TransposeInt64Int16 = transposeInt64Int16 + TransposeInt64Uint16 = transposeInt64Uint16 + TransposeInt64Int32 = transposeInt64Int32 + TransposeInt64Uint32 = transposeInt64Uint32 + TransposeInt64Int64 = transposeInt64Int64 + TransposeInt64Uint64 = transposeInt64Uint64 + + TransposeUint64Int8 = transposeUint64Int8 + TransposeUint64Uint8 = transposeUint64Uint8 + TransposeUint64Int16 = transposeUint64Int16 + TransposeUint64Uint16 = transposeUint64Uint16 + TransposeUint64Int32 = transposeUint64Int32 + TransposeUint64Uint32 = transposeUint64Uint32 + TransposeUint64Int64 = transposeUint64Int64 + TransposeUint64Uint64 = transposeUint64Uint64 +) diff --git a/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_s390x.go.tmpl b/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_s390x.go.tmpl new file mode 100644 index 000000000..d93c8779c --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_s390x.go.tmpl @@ -0,0 +1,34 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !noasm +// +build !noasm + +package utils + +// if building with the 'noasm' tag, then point to the pure go implementations +var ( +{{ $typelist := .In }} +{{range .In}} +{{ $src := .Type -}} +{{ $srcName := .Name -}} +{{ range $typelist -}} +{{ $dest := .Type -}} +{{ $destName := .Name -}} + Transpose{{$srcName}}{{$destName}} = transpose{{$srcName}}{{$destName}} +{{end}} +{{end}} +) diff --git a/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_simd.go.tmpl b/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_simd.go.tmpl new file mode 100644 index 000000000..034d0e9d2 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_simd.go.tmpl @@ -0,0 +1,42 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !noasm +// +build !noasm + +package utils + +import ( + "unsafe" +) + +{{ $arch := .D.arch}} +{{ $typelist := .In}} +{{range .In}} +{{ $src := .Type }} +{{ $srcName := .Name }} +{{ range $typelist}} +{{ $dest := .Type }} +{{ $destName := .Name }} + +//go:noescape +func _transpose_{{printf "%s_%s_%s" $src $dest $arch}}(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transpose{{ $srcName }}{{ $destName }}{{ $arch }}(src []{{$src}}, dest []{{$dest}}, transposeMap []int32) { + _transpose_{{printf "%s_%s_%s" $src $dest $arch}}(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} +{{ end }} +{{ end }} diff --git a/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_sse4_amd64.go b/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_sse4_amd64.go new file mode 100644 index 000000000..241ca74a7 --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_sse4_amd64.go @@ -0,0 +1,473 @@ +// Code generated by transpose_ints_simd.go.tmpl. DO NOT EDIT. + +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !noasm + +package utils + +import ( + "unsafe" +) + +//go:noescape +func _transpose_int8_int8_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt8Int8sse4(src []int8, dest []int8, transposeMap []int32) { + _transpose_int8_int8_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int8_uint8_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt8Uint8sse4(src []int8, dest []uint8, transposeMap []int32) { + _transpose_int8_uint8_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int8_int16_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt8Int16sse4(src []int8, dest []int16, transposeMap []int32) { + _transpose_int8_int16_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int8_uint16_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt8Uint16sse4(src []int8, dest []uint16, transposeMap []int32) { + _transpose_int8_uint16_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int8_int32_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt8Int32sse4(src []int8, dest []int32, transposeMap []int32) { + _transpose_int8_int32_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int8_uint32_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt8Uint32sse4(src []int8, dest []uint32, transposeMap []int32) { + _transpose_int8_uint32_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int8_int64_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt8Int64sse4(src []int8, dest []int64, transposeMap []int32) { + _transpose_int8_int64_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int8_uint64_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt8Uint64sse4(src []int8, dest []uint64, transposeMap []int32) { + _transpose_int8_uint64_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint8_int8_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint8Int8sse4(src []uint8, dest []int8, transposeMap []int32) { + _transpose_uint8_int8_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint8_uint8_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint8Uint8sse4(src []uint8, dest []uint8, transposeMap []int32) { + _transpose_uint8_uint8_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint8_int16_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint8Int16sse4(src []uint8, dest []int16, transposeMap []int32) { + _transpose_uint8_int16_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint8_uint16_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint8Uint16sse4(src []uint8, dest []uint16, transposeMap []int32) { + _transpose_uint8_uint16_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint8_int32_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint8Int32sse4(src []uint8, dest []int32, transposeMap []int32) { + _transpose_uint8_int32_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint8_uint32_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint8Uint32sse4(src []uint8, dest []uint32, transposeMap []int32) { + _transpose_uint8_uint32_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint8_int64_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint8Int64sse4(src []uint8, dest []int64, transposeMap []int32) { + _transpose_uint8_int64_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint8_uint64_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint8Uint64sse4(src []uint8, dest []uint64, transposeMap []int32) { + _transpose_uint8_uint64_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int16_int8_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt16Int8sse4(src []int16, dest []int8, transposeMap []int32) { + _transpose_int16_int8_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int16_uint8_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt16Uint8sse4(src []int16, dest []uint8, transposeMap []int32) { + _transpose_int16_uint8_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int16_int16_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt16Int16sse4(src []int16, dest []int16, transposeMap []int32) { + _transpose_int16_int16_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int16_uint16_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt16Uint16sse4(src []int16, dest []uint16, transposeMap []int32) { + _transpose_int16_uint16_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int16_int32_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt16Int32sse4(src []int16, dest []int32, transposeMap []int32) { + _transpose_int16_int32_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int16_uint32_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt16Uint32sse4(src []int16, dest []uint32, transposeMap []int32) { + _transpose_int16_uint32_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int16_int64_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt16Int64sse4(src []int16, dest []int64, transposeMap []int32) { + _transpose_int16_int64_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int16_uint64_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt16Uint64sse4(src []int16, dest []uint64, transposeMap []int32) { + _transpose_int16_uint64_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint16_int8_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint16Int8sse4(src []uint16, dest []int8, transposeMap []int32) { + _transpose_uint16_int8_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint16_uint8_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint16Uint8sse4(src []uint16, dest []uint8, transposeMap []int32) { + _transpose_uint16_uint8_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint16_int16_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint16Int16sse4(src []uint16, dest []int16, transposeMap []int32) { + _transpose_uint16_int16_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint16_uint16_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint16Uint16sse4(src []uint16, dest []uint16, transposeMap []int32) { + _transpose_uint16_uint16_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint16_int32_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint16Int32sse4(src []uint16, dest []int32, transposeMap []int32) { + _transpose_uint16_int32_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint16_uint32_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint16Uint32sse4(src []uint16, dest []uint32, transposeMap []int32) { + _transpose_uint16_uint32_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint16_int64_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint16Int64sse4(src []uint16, dest []int64, transposeMap []int32) { + _transpose_uint16_int64_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint16_uint64_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint16Uint64sse4(src []uint16, dest []uint64, transposeMap []int32) { + _transpose_uint16_uint64_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int32_int8_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt32Int8sse4(src []int32, dest []int8, transposeMap []int32) { + _transpose_int32_int8_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int32_uint8_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt32Uint8sse4(src []int32, dest []uint8, transposeMap []int32) { + _transpose_int32_uint8_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int32_int16_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt32Int16sse4(src []int32, dest []int16, transposeMap []int32) { + _transpose_int32_int16_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int32_uint16_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt32Uint16sse4(src []int32, dest []uint16, transposeMap []int32) { + _transpose_int32_uint16_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int32_int32_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt32Int32sse4(src []int32, dest []int32, transposeMap []int32) { + _transpose_int32_int32_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int32_uint32_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt32Uint32sse4(src []int32, dest []uint32, transposeMap []int32) { + _transpose_int32_uint32_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int32_int64_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt32Int64sse4(src []int32, dest []int64, transposeMap []int32) { + _transpose_int32_int64_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int32_uint64_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt32Uint64sse4(src []int32, dest []uint64, transposeMap []int32) { + _transpose_int32_uint64_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint32_int8_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint32Int8sse4(src []uint32, dest []int8, transposeMap []int32) { + _transpose_uint32_int8_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint32_uint8_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint32Uint8sse4(src []uint32, dest []uint8, transposeMap []int32) { + _transpose_uint32_uint8_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint32_int16_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint32Int16sse4(src []uint32, dest []int16, transposeMap []int32) { + _transpose_uint32_int16_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint32_uint16_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint32Uint16sse4(src []uint32, dest []uint16, transposeMap []int32) { + _transpose_uint32_uint16_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint32_int32_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint32Int32sse4(src []uint32, dest []int32, transposeMap []int32) { + _transpose_uint32_int32_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint32_uint32_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint32Uint32sse4(src []uint32, dest []uint32, transposeMap []int32) { + _transpose_uint32_uint32_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint32_int64_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint32Int64sse4(src []uint32, dest []int64, transposeMap []int32) { + _transpose_uint32_int64_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint32_uint64_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint32Uint64sse4(src []uint32, dest []uint64, transposeMap []int32) { + _transpose_uint32_uint64_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int64_int8_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt64Int8sse4(src []int64, dest []int8, transposeMap []int32) { + _transpose_int64_int8_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int64_uint8_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt64Uint8sse4(src []int64, dest []uint8, transposeMap []int32) { + _transpose_int64_uint8_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int64_int16_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt64Int16sse4(src []int64, dest []int16, transposeMap []int32) { + _transpose_int64_int16_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int64_uint16_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt64Uint16sse4(src []int64, dest []uint16, transposeMap []int32) { + _transpose_int64_uint16_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int64_int32_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt64Int32sse4(src []int64, dest []int32, transposeMap []int32) { + _transpose_int64_int32_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int64_uint32_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt64Uint32sse4(src []int64, dest []uint32, transposeMap []int32) { + _transpose_int64_uint32_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int64_int64_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt64Int64sse4(src []int64, dest []int64, transposeMap []int32) { + _transpose_int64_int64_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_int64_uint64_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeInt64Uint64sse4(src []int64, dest []uint64, transposeMap []int32) { + _transpose_int64_uint64_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint64_int8_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint64Int8sse4(src []uint64, dest []int8, transposeMap []int32) { + _transpose_uint64_int8_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint64_uint8_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint64Uint8sse4(src []uint64, dest []uint8, transposeMap []int32) { + _transpose_uint64_uint8_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint64_int16_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint64Int16sse4(src []uint64, dest []int16, transposeMap []int32) { + _transpose_uint64_int16_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint64_uint16_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint64Uint16sse4(src []uint64, dest []uint16, transposeMap []int32) { + _transpose_uint64_uint16_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint64_int32_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint64Int32sse4(src []uint64, dest []int32, transposeMap []int32) { + _transpose_uint64_int32_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint64_uint32_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint64Uint32sse4(src []uint64, dest []uint32, transposeMap []int32) { + _transpose_uint64_uint32_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint64_int64_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint64Int64sse4(src []uint64, dest []int64, transposeMap []int32) { + _transpose_uint64_int64_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} + +//go:noescape +func _transpose_uint64_uint64_sse4(src, dest unsafe.Pointer, length int, transposeMap unsafe.Pointer) + +func transposeUint64Uint64sse4(src []uint64, dest []uint64, transposeMap []int32) { + _transpose_uint64_uint64_sse4(unsafe.Pointer(&src[0]), unsafe.Pointer(&dest[0]), len(dest), unsafe.Pointer(&transposeMap[0])) +} diff --git a/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_sse4_amd64.s b/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_sse4_amd64.s new file mode 100644 index 000000000..ee5199a5a --- /dev/null +++ b/vendor/github.com/apache/arrow/go/v14/internal/utils/transpose_ints_sse4_amd64.s @@ -0,0 +1,3074 @@ +//+build !noasm !appengine +// AUTO-GENERATED BY C2GOASM -- DO NOT EDIT + +TEXT ·_transpose_uint8_uint8_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB0_1 + +LBB0_5: + WORD $0xd089 // mov eax, edx + WORD $0xb60f; BYTE $0x17 // movzx edx, byte [rdi] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x1688 // mov byte [rsi], dl + LONG $0x0157b60f // movzx edx, byte [rdi + 1] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x01 // mov byte [rsi + 1], dl + LONG $0x0257b60f // movzx edx, byte [rdi + 2] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x02 // mov byte [rsi + 2], dl + LONG $0x0357b60f // movzx edx, byte [rdi + 3] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x03 // mov byte [rsi + 3], dl + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x04c78348 // add rdi, 4 + LONG $0x04c68348 // add rsi, 4 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB0_5 + +LBB0_1: + WORD $0xd285 // test edx, edx + JLE LBB0_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB0_3: + LONG $0x04b60f42; BYTE $0x07 // movzx eax, byte [rdi + r8] + LONG $0x8104b60f // movzx eax, byte [rcx + 4*rax] + LONG $0x06048842 // mov byte [rsi + r8], al + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB0_3 + +LBB0_4: + RET + +TEXT ·_transpose_int8_uint8_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB1_1 + +LBB1_5: + WORD $0xd089 // mov eax, edx + LONG $0x17be0f48 // movsx rdx, byte [rdi] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x1688 // mov byte [rsi], dl + LONG $0x57be0f48; BYTE $0x01 // movsx rdx, byte [rdi + 1] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x01 // mov byte [rsi + 1], dl + LONG $0x57be0f48; BYTE $0x02 // movsx rdx, byte [rdi + 2] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x02 // mov byte [rsi + 2], dl + LONG $0x57be0f48; BYTE $0x03 // movsx rdx, byte [rdi + 3] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x03 // mov byte [rsi + 3], dl + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x04c78348 // add rdi, 4 + LONG $0x04c68348 // add rsi, 4 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB1_5 + +LBB1_1: + WORD $0xd285 // test edx, edx + JLE LBB1_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB1_3: + LONG $0x04be0f4a; BYTE $0x07 // movsx rax, byte [rdi + r8] + LONG $0x8104b60f // movzx eax, byte [rcx + 4*rax] + LONG $0x06048842 // mov byte [rsi + r8], al + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB1_3 + +LBB1_4: + RET + +TEXT ·_transpose_uint16_uint8_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB2_1 + +LBB2_5: + WORD $0xd089 // mov eax, edx + WORD $0xb70f; BYTE $0x17 // movzx edx, word [rdi] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x1688 // mov byte [rsi], dl + LONG $0x0257b70f // movzx edx, word [rdi + 2] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x01 // mov byte [rsi + 1], dl + LONG $0x0457b70f // movzx edx, word [rdi + 4] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x02 // mov byte [rsi + 2], dl + LONG $0x0657b70f // movzx edx, word [rdi + 6] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x03 // mov byte [rsi + 3], dl + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x08c78348 // add rdi, 8 + LONG $0x04c68348 // add rsi, 4 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB2_5 + +LBB2_1: + WORD $0xd285 // test edx, edx + JLE LBB2_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB2_3: + LONG $0x04b70f42; BYTE $0x47 // movzx eax, word [rdi + 2*r8] + LONG $0x8104b60f // movzx eax, byte [rcx + 4*rax] + LONG $0x06048842 // mov byte [rsi + r8], al + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB2_3 + +LBB2_4: + RET + +TEXT ·_transpose_int16_uint8_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB3_1 + +LBB3_5: + WORD $0xd089 // mov eax, edx + LONG $0x17bf0f48 // movsx rdx, word [rdi] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x1688 // mov byte [rsi], dl + LONG $0x57bf0f48; BYTE $0x02 // movsx rdx, word [rdi + 2] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x01 // mov byte [rsi + 1], dl + LONG $0x57bf0f48; BYTE $0x04 // movsx rdx, word [rdi + 4] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x02 // mov byte [rsi + 2], dl + LONG $0x57bf0f48; BYTE $0x06 // movsx rdx, word [rdi + 6] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x03 // mov byte [rsi + 3], dl + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x08c78348 // add rdi, 8 + LONG $0x04c68348 // add rsi, 4 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB3_5 + +LBB3_1: + WORD $0xd285 // test edx, edx + JLE LBB3_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB3_3: + LONG $0x04bf0f4a; BYTE $0x47 // movsx rax, word [rdi + 2*r8] + LONG $0x8104b60f // movzx eax, byte [rcx + 4*rax] + LONG $0x06048842 // mov byte [rsi + r8], al + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB3_3 + +LBB3_4: + RET + +TEXT ·_transpose_uint32_uint8_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB4_1 + +LBB4_5: + WORD $0xd089 // mov eax, edx + WORD $0x178b // mov edx, dword [rdi] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x1688 // mov byte [rsi], dl + WORD $0x578b; BYTE $0x04 // mov edx, dword [rdi + 4] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x01 // mov byte [rsi + 1], dl + WORD $0x578b; BYTE $0x08 // mov edx, dword [rdi + 8] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x02 // mov byte [rsi + 2], dl + WORD $0x578b; BYTE $0x0c // mov edx, dword [rdi + 12] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x03 // mov byte [rsi + 3], dl + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x10c78348 // add rdi, 16 + LONG $0x04c68348 // add rsi, 4 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB4_5 + +LBB4_1: + WORD $0xd285 // test edx, edx + JLE LBB4_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB4_3: + LONG $0x87048b42 // mov eax, dword [rdi + 4*r8] + LONG $0x8104b60f // movzx eax, byte [rcx + 4*rax] + LONG $0x06048842 // mov byte [rsi + r8], al + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB4_3 + +LBB4_4: + RET + +TEXT ·_transpose_int32_uint8_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB5_1 + +LBB5_5: + WORD $0xd089 // mov eax, edx + WORD $0x6348; BYTE $0x17 // movsxd rdx, dword [rdi] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x1688 // mov byte [rsi], dl + LONG $0x04576348 // movsxd rdx, dword [rdi + 4] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x01 // mov byte [rsi + 1], dl + LONG $0x08576348 // movsxd rdx, dword [rdi + 8] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x02 // mov byte [rsi + 2], dl + LONG $0x0c576348 // movsxd rdx, dword [rdi + 12] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x03 // mov byte [rsi + 3], dl + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x10c78348 // add rdi, 16 + LONG $0x04c68348 // add rsi, 4 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB5_5 + +LBB5_1: + WORD $0xd285 // test edx, edx + JLE LBB5_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB5_3: + LONG $0x8704634a // movsxd rax, dword [rdi + 4*r8] + LONG $0x8104b60f // movzx eax, byte [rcx + 4*rax] + LONG $0x06048842 // mov byte [rsi + r8], al + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB5_3 + +LBB5_4: + RET + +TEXT ·_transpose_uint64_uint8_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB6_1 + +LBB6_5: + WORD $0xd089 // mov eax, edx + WORD $0x8b48; BYTE $0x17 // mov rdx, qword [rdi] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x1688 // mov byte [rsi], dl + LONG $0x08578b48 // mov rdx, qword [rdi + 8] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x01 // mov byte [rsi + 1], dl + LONG $0x10578b48 // mov rdx, qword [rdi + 16] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x02 // mov byte [rsi + 2], dl + LONG $0x18578b48 // mov rdx, qword [rdi + 24] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x03 // mov byte [rsi + 3], dl + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x20c78348 // add rdi, 32 + LONG $0x04c68348 // add rsi, 4 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB6_5 + +LBB6_1: + WORD $0xd285 // test edx, edx + JLE LBB6_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB6_3: + LONG $0xc7048b4a // mov rax, qword [rdi + 8*r8] + LONG $0x8104b60f // movzx eax, byte [rcx + 4*rax] + LONG $0x06048842 // mov byte [rsi + r8], al + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB6_3 + +LBB6_4: + RET + +TEXT ·_transpose_int64_uint8_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB7_1 + +LBB7_5: + WORD $0xd089 // mov eax, edx + WORD $0x8b48; BYTE $0x17 // mov rdx, qword [rdi] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x1688 // mov byte [rsi], dl + LONG $0x08578b48 // mov rdx, qword [rdi + 8] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x01 // mov byte [rsi + 1], dl + LONG $0x10578b48 // mov rdx, qword [rdi + 16] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x02 // mov byte [rsi + 2], dl + LONG $0x18578b48 // mov rdx, qword [rdi + 24] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x03 // mov byte [rsi + 3], dl + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x20c78348 // add rdi, 32 + LONG $0x04c68348 // add rsi, 4 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB7_5 + +LBB7_1: + WORD $0xd285 // test edx, edx + JLE LBB7_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB7_3: + LONG $0xc7048b4a // mov rax, qword [rdi + 8*r8] + LONG $0x8104b60f // movzx eax, byte [rcx + 4*rax] + LONG $0x06048842 // mov byte [rsi + r8], al + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB7_3 + +LBB7_4: + RET + +TEXT ·_transpose_uint8_int8_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB8_1 + +LBB8_5: + WORD $0xd089 // mov eax, edx + WORD $0xb60f; BYTE $0x17 // movzx edx, byte [rdi] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x1688 // mov byte [rsi], dl + LONG $0x0157b60f // movzx edx, byte [rdi + 1] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x01 // mov byte [rsi + 1], dl + LONG $0x0257b60f // movzx edx, byte [rdi + 2] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x02 // mov byte [rsi + 2], dl + LONG $0x0357b60f // movzx edx, byte [rdi + 3] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x03 // mov byte [rsi + 3], dl + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x04c78348 // add rdi, 4 + LONG $0x04c68348 // add rsi, 4 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB8_5 + +LBB8_1: + WORD $0xd285 // test edx, edx + JLE LBB8_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB8_3: + LONG $0x04b60f42; BYTE $0x07 // movzx eax, byte [rdi + r8] + LONG $0x8104b60f // movzx eax, byte [rcx + 4*rax] + LONG $0x06048842 // mov byte [rsi + r8], al + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB8_3 + +LBB8_4: + RET + +TEXT ·_transpose_int8_int8_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB9_1 + +LBB9_5: + WORD $0xd089 // mov eax, edx + LONG $0x17be0f48 // movsx rdx, byte [rdi] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x1688 // mov byte [rsi], dl + LONG $0x57be0f48; BYTE $0x01 // movsx rdx, byte [rdi + 1] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x01 // mov byte [rsi + 1], dl + LONG $0x57be0f48; BYTE $0x02 // movsx rdx, byte [rdi + 2] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x02 // mov byte [rsi + 2], dl + LONG $0x57be0f48; BYTE $0x03 // movsx rdx, byte [rdi + 3] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x03 // mov byte [rsi + 3], dl + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x04c78348 // add rdi, 4 + LONG $0x04c68348 // add rsi, 4 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB9_5 + +LBB9_1: + WORD $0xd285 // test edx, edx + JLE LBB9_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB9_3: + LONG $0x04be0f4a; BYTE $0x07 // movsx rax, byte [rdi + r8] + LONG $0x8104b60f // movzx eax, byte [rcx + 4*rax] + LONG $0x06048842 // mov byte [rsi + r8], al + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB9_3 + +LBB9_4: + RET + +TEXT ·_transpose_uint16_int8_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB10_1 + +LBB10_5: + WORD $0xd089 // mov eax, edx + WORD $0xb70f; BYTE $0x17 // movzx edx, word [rdi] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x1688 // mov byte [rsi], dl + LONG $0x0257b70f // movzx edx, word [rdi + 2] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x01 // mov byte [rsi + 1], dl + LONG $0x0457b70f // movzx edx, word [rdi + 4] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x02 // mov byte [rsi + 2], dl + LONG $0x0657b70f // movzx edx, word [rdi + 6] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x03 // mov byte [rsi + 3], dl + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x08c78348 // add rdi, 8 + LONG $0x04c68348 // add rsi, 4 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB10_5 + +LBB10_1: + WORD $0xd285 // test edx, edx + JLE LBB10_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB10_3: + LONG $0x04b70f42; BYTE $0x47 // movzx eax, word [rdi + 2*r8] + LONG $0x8104b60f // movzx eax, byte [rcx + 4*rax] + LONG $0x06048842 // mov byte [rsi + r8], al + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB10_3 + +LBB10_4: + RET + +TEXT ·_transpose_int16_int8_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB11_1 + +LBB11_5: + WORD $0xd089 // mov eax, edx + LONG $0x17bf0f48 // movsx rdx, word [rdi] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x1688 // mov byte [rsi], dl + LONG $0x57bf0f48; BYTE $0x02 // movsx rdx, word [rdi + 2] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x01 // mov byte [rsi + 1], dl + LONG $0x57bf0f48; BYTE $0x04 // movsx rdx, word [rdi + 4] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x02 // mov byte [rsi + 2], dl + LONG $0x57bf0f48; BYTE $0x06 // movsx rdx, word [rdi + 6] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x03 // mov byte [rsi + 3], dl + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x08c78348 // add rdi, 8 + LONG $0x04c68348 // add rsi, 4 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB11_5 + +LBB11_1: + WORD $0xd285 // test edx, edx + JLE LBB11_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB11_3: + LONG $0x04bf0f4a; BYTE $0x47 // movsx rax, word [rdi + 2*r8] + LONG $0x8104b60f // movzx eax, byte [rcx + 4*rax] + LONG $0x06048842 // mov byte [rsi + r8], al + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB11_3 + +LBB11_4: + RET + +TEXT ·_transpose_uint32_int8_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB12_1 + +LBB12_5: + WORD $0xd089 // mov eax, edx + WORD $0x178b // mov edx, dword [rdi] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x1688 // mov byte [rsi], dl + WORD $0x578b; BYTE $0x04 // mov edx, dword [rdi + 4] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x01 // mov byte [rsi + 1], dl + WORD $0x578b; BYTE $0x08 // mov edx, dword [rdi + 8] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x02 // mov byte [rsi + 2], dl + WORD $0x578b; BYTE $0x0c // mov edx, dword [rdi + 12] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x03 // mov byte [rsi + 3], dl + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x10c78348 // add rdi, 16 + LONG $0x04c68348 // add rsi, 4 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB12_5 + +LBB12_1: + WORD $0xd285 // test edx, edx + JLE LBB12_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB12_3: + LONG $0x87048b42 // mov eax, dword [rdi + 4*r8] + LONG $0x8104b60f // movzx eax, byte [rcx + 4*rax] + LONG $0x06048842 // mov byte [rsi + r8], al + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB12_3 + +LBB12_4: + RET + +TEXT ·_transpose_int32_int8_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB13_1 + +LBB13_5: + WORD $0xd089 // mov eax, edx + WORD $0x6348; BYTE $0x17 // movsxd rdx, dword [rdi] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x1688 // mov byte [rsi], dl + LONG $0x04576348 // movsxd rdx, dword [rdi + 4] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x01 // mov byte [rsi + 1], dl + LONG $0x08576348 // movsxd rdx, dword [rdi + 8] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x02 // mov byte [rsi + 2], dl + LONG $0x0c576348 // movsxd rdx, dword [rdi + 12] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x03 // mov byte [rsi + 3], dl + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x10c78348 // add rdi, 16 + LONG $0x04c68348 // add rsi, 4 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB13_5 + +LBB13_1: + WORD $0xd285 // test edx, edx + JLE LBB13_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB13_3: + LONG $0x8704634a // movsxd rax, dword [rdi + 4*r8] + LONG $0x8104b60f // movzx eax, byte [rcx + 4*rax] + LONG $0x06048842 // mov byte [rsi + r8], al + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB13_3 + +LBB13_4: + RET + +TEXT ·_transpose_uint64_int8_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB14_1 + +LBB14_5: + WORD $0xd089 // mov eax, edx + WORD $0x8b48; BYTE $0x17 // mov rdx, qword [rdi] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x1688 // mov byte [rsi], dl + LONG $0x08578b48 // mov rdx, qword [rdi + 8] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x01 // mov byte [rsi + 1], dl + LONG $0x10578b48 // mov rdx, qword [rdi + 16] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x02 // mov byte [rsi + 2], dl + LONG $0x18578b48 // mov rdx, qword [rdi + 24] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x03 // mov byte [rsi + 3], dl + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x20c78348 // add rdi, 32 + LONG $0x04c68348 // add rsi, 4 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB14_5 + +LBB14_1: + WORD $0xd285 // test edx, edx + JLE LBB14_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB14_3: + LONG $0xc7048b4a // mov rax, qword [rdi + 8*r8] + LONG $0x8104b60f // movzx eax, byte [rcx + 4*rax] + LONG $0x06048842 // mov byte [rsi + r8], al + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB14_3 + +LBB14_4: + RET + +TEXT ·_transpose_int64_int8_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB15_1 + +LBB15_5: + WORD $0xd089 // mov eax, edx + WORD $0x8b48; BYTE $0x17 // mov rdx, qword [rdi] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x1688 // mov byte [rsi], dl + LONG $0x08578b48 // mov rdx, qword [rdi + 8] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x01 // mov byte [rsi + 1], dl + LONG $0x10578b48 // mov rdx, qword [rdi + 16] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x02 // mov byte [rsi + 2], dl + LONG $0x18578b48 // mov rdx, qword [rdi + 24] + LONG $0x9114b60f // movzx edx, byte [rcx + 4*rdx] + WORD $0x5688; BYTE $0x03 // mov byte [rsi + 3], dl + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x20c78348 // add rdi, 32 + LONG $0x04c68348 // add rsi, 4 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB15_5 + +LBB15_1: + WORD $0xd285 // test edx, edx + JLE LBB15_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB15_3: + LONG $0xc7048b4a // mov rax, qword [rdi + 8*r8] + LONG $0x8104b60f // movzx eax, byte [rcx + 4*rax] + LONG $0x06048842 // mov byte [rsi + r8], al + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB15_3 + +LBB15_4: + RET + +TEXT ·_transpose_uint8_uint16_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB16_1 + +LBB16_5: + WORD $0xd089 // mov eax, edx + WORD $0xb60f; BYTE $0x17 // movzx edx, byte [rdi] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + WORD $0x8966; BYTE $0x16 // mov word [rsi], dx + LONG $0x0157b60f // movzx edx, byte [rdi + 1] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x02568966 // mov word [rsi + 2], dx + LONG $0x0257b60f // movzx edx, byte [rdi + 2] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x04568966 // mov word [rsi + 4], dx + LONG $0x0357b60f // movzx edx, byte [rdi + 3] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x06568966 // mov word [rsi + 6], dx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x04c78348 // add rdi, 4 + LONG $0x08c68348 // add rsi, 8 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB16_5 + +LBB16_1: + WORD $0xd285 // test edx, edx + JLE LBB16_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB16_3: + LONG $0x04b60f42; BYTE $0x07 // movzx eax, byte [rdi + r8] + LONG $0x8104b70f // movzx eax, word [rcx + 4*rax] + LONG $0x04894266; BYTE $0x46 // mov word [rsi + 2*r8], ax + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB16_3 + +LBB16_4: + RET + +TEXT ·_transpose_int8_uint16_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB17_1 + +LBB17_5: + WORD $0xd089 // mov eax, edx + LONG $0x17be0f48 // movsx rdx, byte [rdi] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + WORD $0x8966; BYTE $0x16 // mov word [rsi], dx + LONG $0x57be0f48; BYTE $0x01 // movsx rdx, byte [rdi + 1] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x02568966 // mov word [rsi + 2], dx + LONG $0x57be0f48; BYTE $0x02 // movsx rdx, byte [rdi + 2] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x04568966 // mov word [rsi + 4], dx + LONG $0x57be0f48; BYTE $0x03 // movsx rdx, byte [rdi + 3] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x06568966 // mov word [rsi + 6], dx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x04c78348 // add rdi, 4 + LONG $0x08c68348 // add rsi, 8 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB17_5 + +LBB17_1: + WORD $0xd285 // test edx, edx + JLE LBB17_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB17_3: + LONG $0x04be0f4a; BYTE $0x07 // movsx rax, byte [rdi + r8] + LONG $0x8104b70f // movzx eax, word [rcx + 4*rax] + LONG $0x04894266; BYTE $0x46 // mov word [rsi + 2*r8], ax + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB17_3 + +LBB17_4: + RET + +TEXT ·_transpose_uint16_uint16_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB18_1 + +LBB18_5: + WORD $0xd089 // mov eax, edx + WORD $0xb70f; BYTE $0x17 // movzx edx, word [rdi] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + WORD $0x8966; BYTE $0x16 // mov word [rsi], dx + LONG $0x0257b70f // movzx edx, word [rdi + 2] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x02568966 // mov word [rsi + 2], dx + LONG $0x0457b70f // movzx edx, word [rdi + 4] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x04568966 // mov word [rsi + 4], dx + LONG $0x0657b70f // movzx edx, word [rdi + 6] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x06568966 // mov word [rsi + 6], dx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x08c78348 // add rdi, 8 + LONG $0x08c68348 // add rsi, 8 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB18_5 + +LBB18_1: + WORD $0xd285 // test edx, edx + JLE LBB18_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB18_3: + LONG $0x04b70f42; BYTE $0x07 // movzx eax, word [rdi + r8] + LONG $0x8104b70f // movzx eax, word [rcx + 4*rax] + LONG $0x04894266; BYTE $0x06 // mov word [rsi + r8], ax + LONG $0x02c08349 // add r8, 2 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB18_3 + +LBB18_4: + RET + +TEXT ·_transpose_int16_uint16_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB19_1 + +LBB19_5: + WORD $0xd089 // mov eax, edx + LONG $0x17bf0f48 // movsx rdx, word [rdi] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + WORD $0x8966; BYTE $0x16 // mov word [rsi], dx + LONG $0x57bf0f48; BYTE $0x02 // movsx rdx, word [rdi + 2] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x02568966 // mov word [rsi + 2], dx + LONG $0x57bf0f48; BYTE $0x04 // movsx rdx, word [rdi + 4] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x04568966 // mov word [rsi + 4], dx + LONG $0x57bf0f48; BYTE $0x06 // movsx rdx, word [rdi + 6] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x06568966 // mov word [rsi + 6], dx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x08c78348 // add rdi, 8 + LONG $0x08c68348 // add rsi, 8 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB19_5 + +LBB19_1: + WORD $0xd285 // test edx, edx + JLE LBB19_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB19_3: + LONG $0x04bf0f4a; BYTE $0x07 // movsx rax, word [rdi + r8] + LONG $0x8104b70f // movzx eax, word [rcx + 4*rax] + LONG $0x04894266; BYTE $0x06 // mov word [rsi + r8], ax + LONG $0x02c08349 // add r8, 2 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB19_3 + +LBB19_4: + RET + +TEXT ·_transpose_uint32_uint16_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB20_1 + +LBB20_5: + WORD $0xd089 // mov eax, edx + WORD $0x178b // mov edx, dword [rdi] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + WORD $0x8966; BYTE $0x16 // mov word [rsi], dx + WORD $0x578b; BYTE $0x04 // mov edx, dword [rdi + 4] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x02568966 // mov word [rsi + 2], dx + WORD $0x578b; BYTE $0x08 // mov edx, dword [rdi + 8] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x04568966 // mov word [rsi + 4], dx + WORD $0x578b; BYTE $0x0c // mov edx, dword [rdi + 12] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x06568966 // mov word [rsi + 6], dx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x10c78348 // add rdi, 16 + LONG $0x08c68348 // add rsi, 8 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB20_5 + +LBB20_1: + WORD $0xd285 // test edx, edx + JLE LBB20_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB20_3: + LONG $0x47048b42 // mov eax, dword [rdi + 2*r8] + LONG $0x8104b70f // movzx eax, word [rcx + 4*rax] + LONG $0x04894266; BYTE $0x06 // mov word [rsi + r8], ax + LONG $0x02c08349 // add r8, 2 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB20_3 + +LBB20_4: + RET + +TEXT ·_transpose_int32_uint16_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB21_1 + +LBB21_5: + WORD $0xd089 // mov eax, edx + WORD $0x6348; BYTE $0x17 // movsxd rdx, dword [rdi] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + WORD $0x8966; BYTE $0x16 // mov word [rsi], dx + LONG $0x04576348 // movsxd rdx, dword [rdi + 4] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x02568966 // mov word [rsi + 2], dx + LONG $0x08576348 // movsxd rdx, dword [rdi + 8] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x04568966 // mov word [rsi + 4], dx + LONG $0x0c576348 // movsxd rdx, dword [rdi + 12] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x06568966 // mov word [rsi + 6], dx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x10c78348 // add rdi, 16 + LONG $0x08c68348 // add rsi, 8 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB21_5 + +LBB21_1: + WORD $0xd285 // test edx, edx + JLE LBB21_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB21_3: + LONG $0x4704634a // movsxd rax, dword [rdi + 2*r8] + LONG $0x8104b70f // movzx eax, word [rcx + 4*rax] + LONG $0x04894266; BYTE $0x06 // mov word [rsi + r8], ax + LONG $0x02c08349 // add r8, 2 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB21_3 + +LBB21_4: + RET + +TEXT ·_transpose_uint64_uint16_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB22_1 + +LBB22_5: + WORD $0xd089 // mov eax, edx + WORD $0x8b48; BYTE $0x17 // mov rdx, qword [rdi] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + WORD $0x8966; BYTE $0x16 // mov word [rsi], dx + LONG $0x08578b48 // mov rdx, qword [rdi + 8] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x02568966 // mov word [rsi + 2], dx + LONG $0x10578b48 // mov rdx, qword [rdi + 16] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x04568966 // mov word [rsi + 4], dx + LONG $0x18578b48 // mov rdx, qword [rdi + 24] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x06568966 // mov word [rsi + 6], dx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x20c78348 // add rdi, 32 + LONG $0x08c68348 // add rsi, 8 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB22_5 + +LBB22_1: + WORD $0xd285 // test edx, edx + JLE LBB22_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB22_3: + LONG $0x87048b4a // mov rax, qword [rdi + 4*r8] + LONG $0x8104b70f // movzx eax, word [rcx + 4*rax] + LONG $0x04894266; BYTE $0x06 // mov word [rsi + r8], ax + LONG $0x02c08349 // add r8, 2 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB22_3 + +LBB22_4: + RET + +TEXT ·_transpose_int64_uint16_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB23_1 + +LBB23_5: + WORD $0xd089 // mov eax, edx + WORD $0x8b48; BYTE $0x17 // mov rdx, qword [rdi] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + WORD $0x8966; BYTE $0x16 // mov word [rsi], dx + LONG $0x08578b48 // mov rdx, qword [rdi + 8] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x02568966 // mov word [rsi + 2], dx + LONG $0x10578b48 // mov rdx, qword [rdi + 16] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x04568966 // mov word [rsi + 4], dx + LONG $0x18578b48 // mov rdx, qword [rdi + 24] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x06568966 // mov word [rsi + 6], dx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x20c78348 // add rdi, 32 + LONG $0x08c68348 // add rsi, 8 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB23_5 + +LBB23_1: + WORD $0xd285 // test edx, edx + JLE LBB23_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB23_3: + LONG $0x87048b4a // mov rax, qword [rdi + 4*r8] + LONG $0x8104b70f // movzx eax, word [rcx + 4*rax] + LONG $0x04894266; BYTE $0x06 // mov word [rsi + r8], ax + LONG $0x02c08349 // add r8, 2 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB23_3 + +LBB23_4: + RET + +TEXT ·_transpose_uint8_int16_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB24_1 + +LBB24_5: + WORD $0xd089 // mov eax, edx + WORD $0xb60f; BYTE $0x17 // movzx edx, byte [rdi] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + WORD $0x8966; BYTE $0x16 // mov word [rsi], dx + LONG $0x0157b60f // movzx edx, byte [rdi + 1] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x02568966 // mov word [rsi + 2], dx + LONG $0x0257b60f // movzx edx, byte [rdi + 2] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x04568966 // mov word [rsi + 4], dx + LONG $0x0357b60f // movzx edx, byte [rdi + 3] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x06568966 // mov word [rsi + 6], dx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x04c78348 // add rdi, 4 + LONG $0x08c68348 // add rsi, 8 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB24_5 + +LBB24_1: + WORD $0xd285 // test edx, edx + JLE LBB24_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB24_3: + LONG $0x04b60f42; BYTE $0x07 // movzx eax, byte [rdi + r8] + LONG $0x8104b70f // movzx eax, word [rcx + 4*rax] + LONG $0x04894266; BYTE $0x46 // mov word [rsi + 2*r8], ax + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB24_3 + +LBB24_4: + RET + +TEXT ·_transpose_int8_int16_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB25_1 + +LBB25_5: + WORD $0xd089 // mov eax, edx + LONG $0x17be0f48 // movsx rdx, byte [rdi] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + WORD $0x8966; BYTE $0x16 // mov word [rsi], dx + LONG $0x57be0f48; BYTE $0x01 // movsx rdx, byte [rdi + 1] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x02568966 // mov word [rsi + 2], dx + LONG $0x57be0f48; BYTE $0x02 // movsx rdx, byte [rdi + 2] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x04568966 // mov word [rsi + 4], dx + LONG $0x57be0f48; BYTE $0x03 // movsx rdx, byte [rdi + 3] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x06568966 // mov word [rsi + 6], dx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x04c78348 // add rdi, 4 + LONG $0x08c68348 // add rsi, 8 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB25_5 + +LBB25_1: + WORD $0xd285 // test edx, edx + JLE LBB25_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB25_3: + LONG $0x04be0f4a; BYTE $0x07 // movsx rax, byte [rdi + r8] + LONG $0x8104b70f // movzx eax, word [rcx + 4*rax] + LONG $0x04894266; BYTE $0x46 // mov word [rsi + 2*r8], ax + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB25_3 + +LBB25_4: + RET + +TEXT ·_transpose_uint16_int16_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB26_1 + +LBB26_5: + WORD $0xd089 // mov eax, edx + WORD $0xb70f; BYTE $0x17 // movzx edx, word [rdi] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + WORD $0x8966; BYTE $0x16 // mov word [rsi], dx + LONG $0x0257b70f // movzx edx, word [rdi + 2] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x02568966 // mov word [rsi + 2], dx + LONG $0x0457b70f // movzx edx, word [rdi + 4] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x04568966 // mov word [rsi + 4], dx + LONG $0x0657b70f // movzx edx, word [rdi + 6] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x06568966 // mov word [rsi + 6], dx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x08c78348 // add rdi, 8 + LONG $0x08c68348 // add rsi, 8 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB26_5 + +LBB26_1: + WORD $0xd285 // test edx, edx + JLE LBB26_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB26_3: + LONG $0x04b70f42; BYTE $0x07 // movzx eax, word [rdi + r8] + LONG $0x8104b70f // movzx eax, word [rcx + 4*rax] + LONG $0x04894266; BYTE $0x06 // mov word [rsi + r8], ax + LONG $0x02c08349 // add r8, 2 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB26_3 + +LBB26_4: + RET + +TEXT ·_transpose_int16_int16_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB27_1 + +LBB27_5: + WORD $0xd089 // mov eax, edx + LONG $0x17bf0f48 // movsx rdx, word [rdi] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + WORD $0x8966; BYTE $0x16 // mov word [rsi], dx + LONG $0x57bf0f48; BYTE $0x02 // movsx rdx, word [rdi + 2] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x02568966 // mov word [rsi + 2], dx + LONG $0x57bf0f48; BYTE $0x04 // movsx rdx, word [rdi + 4] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x04568966 // mov word [rsi + 4], dx + LONG $0x57bf0f48; BYTE $0x06 // movsx rdx, word [rdi + 6] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x06568966 // mov word [rsi + 6], dx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x08c78348 // add rdi, 8 + LONG $0x08c68348 // add rsi, 8 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB27_5 + +LBB27_1: + WORD $0xd285 // test edx, edx + JLE LBB27_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB27_3: + LONG $0x04bf0f4a; BYTE $0x07 // movsx rax, word [rdi + r8] + LONG $0x8104b70f // movzx eax, word [rcx + 4*rax] + LONG $0x04894266; BYTE $0x06 // mov word [rsi + r8], ax + LONG $0x02c08349 // add r8, 2 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB27_3 + +LBB27_4: + RET + +TEXT ·_transpose_uint32_int16_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB28_1 + +LBB28_5: + WORD $0xd089 // mov eax, edx + WORD $0x178b // mov edx, dword [rdi] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + WORD $0x8966; BYTE $0x16 // mov word [rsi], dx + WORD $0x578b; BYTE $0x04 // mov edx, dword [rdi + 4] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x02568966 // mov word [rsi + 2], dx + WORD $0x578b; BYTE $0x08 // mov edx, dword [rdi + 8] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x04568966 // mov word [rsi + 4], dx + WORD $0x578b; BYTE $0x0c // mov edx, dword [rdi + 12] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x06568966 // mov word [rsi + 6], dx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x10c78348 // add rdi, 16 + LONG $0x08c68348 // add rsi, 8 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB28_5 + +LBB28_1: + WORD $0xd285 // test edx, edx + JLE LBB28_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB28_3: + LONG $0x47048b42 // mov eax, dword [rdi + 2*r8] + LONG $0x8104b70f // movzx eax, word [rcx + 4*rax] + LONG $0x04894266; BYTE $0x06 // mov word [rsi + r8], ax + LONG $0x02c08349 // add r8, 2 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB28_3 + +LBB28_4: + RET + +TEXT ·_transpose_int32_int16_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB29_1 + +LBB29_5: + WORD $0xd089 // mov eax, edx + WORD $0x6348; BYTE $0x17 // movsxd rdx, dword [rdi] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + WORD $0x8966; BYTE $0x16 // mov word [rsi], dx + LONG $0x04576348 // movsxd rdx, dword [rdi + 4] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x02568966 // mov word [rsi + 2], dx + LONG $0x08576348 // movsxd rdx, dword [rdi + 8] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x04568966 // mov word [rsi + 4], dx + LONG $0x0c576348 // movsxd rdx, dword [rdi + 12] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x06568966 // mov word [rsi + 6], dx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x10c78348 // add rdi, 16 + LONG $0x08c68348 // add rsi, 8 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB29_5 + +LBB29_1: + WORD $0xd285 // test edx, edx + JLE LBB29_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB29_3: + LONG $0x4704634a // movsxd rax, dword [rdi + 2*r8] + LONG $0x8104b70f // movzx eax, word [rcx + 4*rax] + LONG $0x04894266; BYTE $0x06 // mov word [rsi + r8], ax + LONG $0x02c08349 // add r8, 2 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB29_3 + +LBB29_4: + RET + +TEXT ·_transpose_uint64_int16_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB30_1 + +LBB30_5: + WORD $0xd089 // mov eax, edx + WORD $0x8b48; BYTE $0x17 // mov rdx, qword [rdi] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + WORD $0x8966; BYTE $0x16 // mov word [rsi], dx + LONG $0x08578b48 // mov rdx, qword [rdi + 8] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x02568966 // mov word [rsi + 2], dx + LONG $0x10578b48 // mov rdx, qword [rdi + 16] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x04568966 // mov word [rsi + 4], dx + LONG $0x18578b48 // mov rdx, qword [rdi + 24] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x06568966 // mov word [rsi + 6], dx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x20c78348 // add rdi, 32 + LONG $0x08c68348 // add rsi, 8 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB30_5 + +LBB30_1: + WORD $0xd285 // test edx, edx + JLE LBB30_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB30_3: + LONG $0x87048b4a // mov rax, qword [rdi + 4*r8] + LONG $0x8104b70f // movzx eax, word [rcx + 4*rax] + LONG $0x04894266; BYTE $0x06 // mov word [rsi + r8], ax + LONG $0x02c08349 // add r8, 2 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB30_3 + +LBB30_4: + RET + +TEXT ·_transpose_int64_int16_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB31_1 + +LBB31_5: + WORD $0xd089 // mov eax, edx + WORD $0x8b48; BYTE $0x17 // mov rdx, qword [rdi] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + WORD $0x8966; BYTE $0x16 // mov word [rsi], dx + LONG $0x08578b48 // mov rdx, qword [rdi + 8] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x02568966 // mov word [rsi + 2], dx + LONG $0x10578b48 // mov rdx, qword [rdi + 16] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x04568966 // mov word [rsi + 4], dx + LONG $0x18578b48 // mov rdx, qword [rdi + 24] + LONG $0x9114b70f // movzx edx, word [rcx + 4*rdx] + LONG $0x06568966 // mov word [rsi + 6], dx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x20c78348 // add rdi, 32 + LONG $0x08c68348 // add rsi, 8 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB31_5 + +LBB31_1: + WORD $0xd285 // test edx, edx + JLE LBB31_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB31_3: + LONG $0x87048b4a // mov rax, qword [rdi + 4*r8] + LONG $0x8104b70f // movzx eax, word [rcx + 4*rax] + LONG $0x04894266; BYTE $0x06 // mov word [rsi + r8], ax + LONG $0x02c08349 // add r8, 2 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB31_3 + +LBB31_4: + RET + +TEXT ·_transpose_uint8_uint32_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB32_1 + +LBB32_5: + WORD $0xd089 // mov eax, edx + WORD $0xb60f; BYTE $0x17 // movzx edx, byte [rdi] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x1689 // mov dword [rsi], edx + LONG $0x0157b60f // movzx edx, byte [rdi + 1] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x04 // mov dword [rsi + 4], edx + LONG $0x0257b60f // movzx edx, byte [rdi + 2] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x08 // mov dword [rsi + 8], edx + LONG $0x0357b60f // movzx edx, byte [rdi + 3] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x0c // mov dword [rsi + 12], edx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x04c78348 // add rdi, 4 + LONG $0x10c68348 // add rsi, 16 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB32_5 + +LBB32_1: + WORD $0xd285 // test edx, edx + JLE LBB32_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB32_3: + LONG $0x04b60f42; BYTE $0x07 // movzx eax, byte [rdi + r8] + WORD $0x048b; BYTE $0x81 // mov eax, dword [rcx + 4*rax] + LONG $0x86048942 // mov dword [rsi + 4*r8], eax + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB32_3 + +LBB32_4: + RET + +TEXT ·_transpose_int8_uint32_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB33_1 + +LBB33_5: + WORD $0xd089 // mov eax, edx + LONG $0x17be0f48 // movsx rdx, byte [rdi] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x1689 // mov dword [rsi], edx + LONG $0x57be0f48; BYTE $0x01 // movsx rdx, byte [rdi + 1] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x04 // mov dword [rsi + 4], edx + LONG $0x57be0f48; BYTE $0x02 // movsx rdx, byte [rdi + 2] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x08 // mov dword [rsi + 8], edx + LONG $0x57be0f48; BYTE $0x03 // movsx rdx, byte [rdi + 3] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x0c // mov dword [rsi + 12], edx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x04c78348 // add rdi, 4 + LONG $0x10c68348 // add rsi, 16 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB33_5 + +LBB33_1: + WORD $0xd285 // test edx, edx + JLE LBB33_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB33_3: + LONG $0x04be0f4a; BYTE $0x07 // movsx rax, byte [rdi + r8] + WORD $0x048b; BYTE $0x81 // mov eax, dword [rcx + 4*rax] + LONG $0x86048942 // mov dword [rsi + 4*r8], eax + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB33_3 + +LBB33_4: + RET + +TEXT ·_transpose_uint16_uint32_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB34_1 + +LBB34_5: + WORD $0xd089 // mov eax, edx + WORD $0xb70f; BYTE $0x17 // movzx edx, word [rdi] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x1689 // mov dword [rsi], edx + LONG $0x0257b70f // movzx edx, word [rdi + 2] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x04 // mov dword [rsi + 4], edx + LONG $0x0457b70f // movzx edx, word [rdi + 4] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x08 // mov dword [rsi + 8], edx + LONG $0x0657b70f // movzx edx, word [rdi + 6] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x0c // mov dword [rsi + 12], edx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x08c78348 // add rdi, 8 + LONG $0x10c68348 // add rsi, 16 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB34_5 + +LBB34_1: + WORD $0xd285 // test edx, edx + JLE LBB34_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB34_3: + LONG $0x04b70f42; BYTE $0x07 // movzx eax, word [rdi + r8] + WORD $0x048b; BYTE $0x81 // mov eax, dword [rcx + 4*rax] + LONG $0x46048942 // mov dword [rsi + 2*r8], eax + LONG $0x02c08349 // add r8, 2 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB34_3 + +LBB34_4: + RET + +TEXT ·_transpose_int16_uint32_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB35_1 + +LBB35_5: + WORD $0xd089 // mov eax, edx + LONG $0x17bf0f48 // movsx rdx, word [rdi] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x1689 // mov dword [rsi], edx + LONG $0x57bf0f48; BYTE $0x02 // movsx rdx, word [rdi + 2] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x04 // mov dword [rsi + 4], edx + LONG $0x57bf0f48; BYTE $0x04 // movsx rdx, word [rdi + 4] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x08 // mov dword [rsi + 8], edx + LONG $0x57bf0f48; BYTE $0x06 // movsx rdx, word [rdi + 6] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x0c // mov dword [rsi + 12], edx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x08c78348 // add rdi, 8 + LONG $0x10c68348 // add rsi, 16 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB35_5 + +LBB35_1: + WORD $0xd285 // test edx, edx + JLE LBB35_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB35_3: + LONG $0x04bf0f4a; BYTE $0x07 // movsx rax, word [rdi + r8] + WORD $0x048b; BYTE $0x81 // mov eax, dword [rcx + 4*rax] + LONG $0x46048942 // mov dword [rsi + 2*r8], eax + LONG $0x02c08349 // add r8, 2 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB35_3 + +LBB35_4: + RET + +TEXT ·_transpose_uint32_uint32_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB36_1 + +LBB36_5: + WORD $0xd089 // mov eax, edx + WORD $0x178b // mov edx, dword [rdi] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x1689 // mov dword [rsi], edx + WORD $0x578b; BYTE $0x04 // mov edx, dword [rdi + 4] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x04 // mov dword [rsi + 4], edx + WORD $0x578b; BYTE $0x08 // mov edx, dword [rdi + 8] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x08 // mov dword [rsi + 8], edx + WORD $0x578b; BYTE $0x0c // mov edx, dword [rdi + 12] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x0c // mov dword [rsi + 12], edx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x10c78348 // add rdi, 16 + LONG $0x10c68348 // add rsi, 16 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB36_5 + +LBB36_1: + WORD $0xd285 // test edx, edx + JLE LBB36_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB36_3: + LONG $0x07048b42 // mov eax, dword [rdi + r8] + WORD $0x048b; BYTE $0x81 // mov eax, dword [rcx + 4*rax] + LONG $0x06048942 // mov dword [rsi + r8], eax + LONG $0x04c08349 // add r8, 4 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB36_3 + +LBB36_4: + RET + +TEXT ·_transpose_int32_uint32_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB37_1 + +LBB37_5: + WORD $0xd089 // mov eax, edx + WORD $0x6348; BYTE $0x17 // movsxd rdx, dword [rdi] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x1689 // mov dword [rsi], edx + LONG $0x04576348 // movsxd rdx, dword [rdi + 4] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x04 // mov dword [rsi + 4], edx + LONG $0x08576348 // movsxd rdx, dword [rdi + 8] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x08 // mov dword [rsi + 8], edx + LONG $0x0c576348 // movsxd rdx, dword [rdi + 12] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x0c // mov dword [rsi + 12], edx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x10c78348 // add rdi, 16 + LONG $0x10c68348 // add rsi, 16 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB37_5 + +LBB37_1: + WORD $0xd285 // test edx, edx + JLE LBB37_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB37_3: + LONG $0x0704634a // movsxd rax, dword [rdi + r8] + WORD $0x048b; BYTE $0x81 // mov eax, dword [rcx + 4*rax] + LONG $0x06048942 // mov dword [rsi + r8], eax + LONG $0x04c08349 // add r8, 4 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB37_3 + +LBB37_4: + RET + +TEXT ·_transpose_uint64_uint32_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB38_1 + +LBB38_5: + WORD $0xd089 // mov eax, edx + WORD $0x8b48; BYTE $0x17 // mov rdx, qword [rdi] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x1689 // mov dword [rsi], edx + LONG $0x08578b48 // mov rdx, qword [rdi + 8] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x04 // mov dword [rsi + 4], edx + LONG $0x10578b48 // mov rdx, qword [rdi + 16] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x08 // mov dword [rsi + 8], edx + LONG $0x18578b48 // mov rdx, qword [rdi + 24] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x0c // mov dword [rsi + 12], edx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x20c78348 // add rdi, 32 + LONG $0x10c68348 // add rsi, 16 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB38_5 + +LBB38_1: + WORD $0xd285 // test edx, edx + JLE LBB38_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB38_3: + LONG $0x47048b4a // mov rax, qword [rdi + 2*r8] + WORD $0x048b; BYTE $0x81 // mov eax, dword [rcx + 4*rax] + LONG $0x06048942 // mov dword [rsi + r8], eax + LONG $0x04c08349 // add r8, 4 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB38_3 + +LBB38_4: + RET + +TEXT ·_transpose_int64_uint32_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB39_1 + +LBB39_5: + WORD $0xd089 // mov eax, edx + WORD $0x8b48; BYTE $0x17 // mov rdx, qword [rdi] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x1689 // mov dword [rsi], edx + LONG $0x08578b48 // mov rdx, qword [rdi + 8] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x04 // mov dword [rsi + 4], edx + LONG $0x10578b48 // mov rdx, qword [rdi + 16] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x08 // mov dword [rsi + 8], edx + LONG $0x18578b48 // mov rdx, qword [rdi + 24] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x0c // mov dword [rsi + 12], edx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x20c78348 // add rdi, 32 + LONG $0x10c68348 // add rsi, 16 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB39_5 + +LBB39_1: + WORD $0xd285 // test edx, edx + JLE LBB39_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB39_3: + LONG $0x47048b4a // mov rax, qword [rdi + 2*r8] + WORD $0x048b; BYTE $0x81 // mov eax, dword [rcx + 4*rax] + LONG $0x06048942 // mov dword [rsi + r8], eax + LONG $0x04c08349 // add r8, 4 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB39_3 + +LBB39_4: + RET + +TEXT ·_transpose_uint8_int32_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB40_1 + +LBB40_5: + WORD $0xd089 // mov eax, edx + WORD $0xb60f; BYTE $0x17 // movzx edx, byte [rdi] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x1689 // mov dword [rsi], edx + LONG $0x0157b60f // movzx edx, byte [rdi + 1] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x04 // mov dword [rsi + 4], edx + LONG $0x0257b60f // movzx edx, byte [rdi + 2] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x08 // mov dword [rsi + 8], edx + LONG $0x0357b60f // movzx edx, byte [rdi + 3] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x0c // mov dword [rsi + 12], edx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x04c78348 // add rdi, 4 + LONG $0x10c68348 // add rsi, 16 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB40_5 + +LBB40_1: + WORD $0xd285 // test edx, edx + JLE LBB40_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB40_3: + LONG $0x04b60f42; BYTE $0x07 // movzx eax, byte [rdi + r8] + WORD $0x048b; BYTE $0x81 // mov eax, dword [rcx + 4*rax] + LONG $0x86048942 // mov dword [rsi + 4*r8], eax + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB40_3 + +LBB40_4: + RET + +TEXT ·_transpose_int8_int32_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB41_1 + +LBB41_5: + WORD $0xd089 // mov eax, edx + LONG $0x17be0f48 // movsx rdx, byte [rdi] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x1689 // mov dword [rsi], edx + LONG $0x57be0f48; BYTE $0x01 // movsx rdx, byte [rdi + 1] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x04 // mov dword [rsi + 4], edx + LONG $0x57be0f48; BYTE $0x02 // movsx rdx, byte [rdi + 2] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x08 // mov dword [rsi + 8], edx + LONG $0x57be0f48; BYTE $0x03 // movsx rdx, byte [rdi + 3] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x0c // mov dword [rsi + 12], edx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x04c78348 // add rdi, 4 + LONG $0x10c68348 // add rsi, 16 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB41_5 + +LBB41_1: + WORD $0xd285 // test edx, edx + JLE LBB41_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB41_3: + LONG $0x04be0f4a; BYTE $0x07 // movsx rax, byte [rdi + r8] + WORD $0x048b; BYTE $0x81 // mov eax, dword [rcx + 4*rax] + LONG $0x86048942 // mov dword [rsi + 4*r8], eax + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB41_3 + +LBB41_4: + RET + +TEXT ·_transpose_uint16_int32_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB42_1 + +LBB42_5: + WORD $0xd089 // mov eax, edx + WORD $0xb70f; BYTE $0x17 // movzx edx, word [rdi] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x1689 // mov dword [rsi], edx + LONG $0x0257b70f // movzx edx, word [rdi + 2] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x04 // mov dword [rsi + 4], edx + LONG $0x0457b70f // movzx edx, word [rdi + 4] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x08 // mov dword [rsi + 8], edx + LONG $0x0657b70f // movzx edx, word [rdi + 6] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x0c // mov dword [rsi + 12], edx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x08c78348 // add rdi, 8 + LONG $0x10c68348 // add rsi, 16 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB42_5 + +LBB42_1: + WORD $0xd285 // test edx, edx + JLE LBB42_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB42_3: + LONG $0x04b70f42; BYTE $0x07 // movzx eax, word [rdi + r8] + WORD $0x048b; BYTE $0x81 // mov eax, dword [rcx + 4*rax] + LONG $0x46048942 // mov dword [rsi + 2*r8], eax + LONG $0x02c08349 // add r8, 2 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB42_3 + +LBB42_4: + RET + +TEXT ·_transpose_int16_int32_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB43_1 + +LBB43_5: + WORD $0xd089 // mov eax, edx + LONG $0x17bf0f48 // movsx rdx, word [rdi] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x1689 // mov dword [rsi], edx + LONG $0x57bf0f48; BYTE $0x02 // movsx rdx, word [rdi + 2] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x04 // mov dword [rsi + 4], edx + LONG $0x57bf0f48; BYTE $0x04 // movsx rdx, word [rdi + 4] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x08 // mov dword [rsi + 8], edx + LONG $0x57bf0f48; BYTE $0x06 // movsx rdx, word [rdi + 6] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x0c // mov dword [rsi + 12], edx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x08c78348 // add rdi, 8 + LONG $0x10c68348 // add rsi, 16 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB43_5 + +LBB43_1: + WORD $0xd285 // test edx, edx + JLE LBB43_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB43_3: + LONG $0x04bf0f4a; BYTE $0x07 // movsx rax, word [rdi + r8] + WORD $0x048b; BYTE $0x81 // mov eax, dword [rcx + 4*rax] + LONG $0x46048942 // mov dword [rsi + 2*r8], eax + LONG $0x02c08349 // add r8, 2 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB43_3 + +LBB43_4: + RET + +TEXT ·_transpose_uint32_int32_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB44_1 + +LBB44_5: + WORD $0xd089 // mov eax, edx + WORD $0x178b // mov edx, dword [rdi] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x1689 // mov dword [rsi], edx + WORD $0x578b; BYTE $0x04 // mov edx, dword [rdi + 4] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x04 // mov dword [rsi + 4], edx + WORD $0x578b; BYTE $0x08 // mov edx, dword [rdi + 8] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x08 // mov dword [rsi + 8], edx + WORD $0x578b; BYTE $0x0c // mov edx, dword [rdi + 12] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x0c // mov dword [rsi + 12], edx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x10c78348 // add rdi, 16 + LONG $0x10c68348 // add rsi, 16 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB44_5 + +LBB44_1: + WORD $0xd285 // test edx, edx + JLE LBB44_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB44_3: + LONG $0x07048b42 // mov eax, dword [rdi + r8] + WORD $0x048b; BYTE $0x81 // mov eax, dword [rcx + 4*rax] + LONG $0x06048942 // mov dword [rsi + r8], eax + LONG $0x04c08349 // add r8, 4 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB44_3 + +LBB44_4: + RET + +TEXT ·_transpose_int32_int32_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB45_1 + +LBB45_5: + WORD $0xd089 // mov eax, edx + WORD $0x6348; BYTE $0x17 // movsxd rdx, dword [rdi] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x1689 // mov dword [rsi], edx + LONG $0x04576348 // movsxd rdx, dword [rdi + 4] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x04 // mov dword [rsi + 4], edx + LONG $0x08576348 // movsxd rdx, dword [rdi + 8] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x08 // mov dword [rsi + 8], edx + LONG $0x0c576348 // movsxd rdx, dword [rdi + 12] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x0c // mov dword [rsi + 12], edx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x10c78348 // add rdi, 16 + LONG $0x10c68348 // add rsi, 16 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB45_5 + +LBB45_1: + WORD $0xd285 // test edx, edx + JLE LBB45_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB45_3: + LONG $0x0704634a // movsxd rax, dword [rdi + r8] + WORD $0x048b; BYTE $0x81 // mov eax, dword [rcx + 4*rax] + LONG $0x06048942 // mov dword [rsi + r8], eax + LONG $0x04c08349 // add r8, 4 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB45_3 + +LBB45_4: + RET + +TEXT ·_transpose_uint64_int32_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB46_1 + +LBB46_5: + WORD $0xd089 // mov eax, edx + WORD $0x8b48; BYTE $0x17 // mov rdx, qword [rdi] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x1689 // mov dword [rsi], edx + LONG $0x08578b48 // mov rdx, qword [rdi + 8] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x04 // mov dword [rsi + 4], edx + LONG $0x10578b48 // mov rdx, qword [rdi + 16] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x08 // mov dword [rsi + 8], edx + LONG $0x18578b48 // mov rdx, qword [rdi + 24] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x0c // mov dword [rsi + 12], edx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x20c78348 // add rdi, 32 + LONG $0x10c68348 // add rsi, 16 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB46_5 + +LBB46_1: + WORD $0xd285 // test edx, edx + JLE LBB46_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB46_3: + LONG $0x47048b4a // mov rax, qword [rdi + 2*r8] + WORD $0x048b; BYTE $0x81 // mov eax, dword [rcx + 4*rax] + LONG $0x06048942 // mov dword [rsi + r8], eax + LONG $0x04c08349 // add r8, 4 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB46_3 + +LBB46_4: + RET + +TEXT ·_transpose_int64_int32_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB47_1 + +LBB47_5: + WORD $0xd089 // mov eax, edx + WORD $0x8b48; BYTE $0x17 // mov rdx, qword [rdi] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x1689 // mov dword [rsi], edx + LONG $0x08578b48 // mov rdx, qword [rdi + 8] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x04 // mov dword [rsi + 4], edx + LONG $0x10578b48 // mov rdx, qword [rdi + 16] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x08 // mov dword [rsi + 8], edx + LONG $0x18578b48 // mov rdx, qword [rdi + 24] + WORD $0x148b; BYTE $0x91 // mov edx, dword [rcx + 4*rdx] + WORD $0x5689; BYTE $0x0c // mov dword [rsi + 12], edx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x20c78348 // add rdi, 32 + LONG $0x10c68348 // add rsi, 16 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB47_5 + +LBB47_1: + WORD $0xd285 // test edx, edx + JLE LBB47_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB47_3: + LONG $0x47048b4a // mov rax, qword [rdi + 2*r8] + WORD $0x048b; BYTE $0x81 // mov eax, dword [rcx + 4*rax] + LONG $0x06048942 // mov dword [rsi + r8], eax + LONG $0x04c08349 // add r8, 4 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB47_3 + +LBB47_4: + RET + +TEXT ·_transpose_uint8_uint64_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB48_1 + +LBB48_5: + WORD $0xd089 // mov eax, edx + WORD $0xb60f; BYTE $0x17 // movzx edx, byte [rdi] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + WORD $0x8948; BYTE $0x16 // mov qword [rsi], rdx + LONG $0x0157b60f // movzx edx, byte [rdi + 1] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x08568948 // mov qword [rsi + 8], rdx + LONG $0x0257b60f // movzx edx, byte [rdi + 2] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x10568948 // mov qword [rsi + 16], rdx + LONG $0x0357b60f // movzx edx, byte [rdi + 3] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x18568948 // mov qword [rsi + 24], rdx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x04c78348 // add rdi, 4 + LONG $0x20c68348 // add rsi, 32 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB48_5 + +LBB48_1: + WORD $0xd285 // test edx, edx + JLE LBB48_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB48_3: + LONG $0x04b60f42; BYTE $0x07 // movzx eax, byte [rdi + r8] + LONG $0x81046348 // movsxd rax, dword [rcx + 4*rax] + LONG $0xc604894a // mov qword [rsi + 8*r8], rax + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB48_3 + +LBB48_4: + RET + +TEXT ·_transpose_int8_uint64_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB49_1 + +LBB49_5: + WORD $0xd089 // mov eax, edx + LONG $0x17be0f48 // movsx rdx, byte [rdi] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + WORD $0x8948; BYTE $0x16 // mov qword [rsi], rdx + LONG $0x57be0f48; BYTE $0x01 // movsx rdx, byte [rdi + 1] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x08568948 // mov qword [rsi + 8], rdx + LONG $0x57be0f48; BYTE $0x02 // movsx rdx, byte [rdi + 2] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x10568948 // mov qword [rsi + 16], rdx + LONG $0x57be0f48; BYTE $0x03 // movsx rdx, byte [rdi + 3] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x18568948 // mov qword [rsi + 24], rdx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x04c78348 // add rdi, 4 + LONG $0x20c68348 // add rsi, 32 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB49_5 + +LBB49_1: + WORD $0xd285 // test edx, edx + JLE LBB49_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB49_3: + LONG $0x04be0f4a; BYTE $0x07 // movsx rax, byte [rdi + r8] + LONG $0x81046348 // movsxd rax, dword [rcx + 4*rax] + LONG $0xc604894a // mov qword [rsi + 8*r8], rax + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB49_3 + +LBB49_4: + RET + +TEXT ·_transpose_uint16_uint64_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB50_1 + +LBB50_5: + WORD $0xd089 // mov eax, edx + WORD $0xb70f; BYTE $0x17 // movzx edx, word [rdi] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + WORD $0x8948; BYTE $0x16 // mov qword [rsi], rdx + LONG $0x0257b70f // movzx edx, word [rdi + 2] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x08568948 // mov qword [rsi + 8], rdx + LONG $0x0457b70f // movzx edx, word [rdi + 4] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x10568948 // mov qword [rsi + 16], rdx + LONG $0x0657b70f // movzx edx, word [rdi + 6] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x18568948 // mov qword [rsi + 24], rdx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x08c78348 // add rdi, 8 + LONG $0x20c68348 // add rsi, 32 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB50_5 + +LBB50_1: + WORD $0xd285 // test edx, edx + JLE LBB50_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB50_3: + LONG $0x04b70f42; BYTE $0x07 // movzx eax, word [rdi + r8] + LONG $0x81046348 // movsxd rax, dword [rcx + 4*rax] + LONG $0x8604894a // mov qword [rsi + 4*r8], rax + LONG $0x02c08349 // add r8, 2 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB50_3 + +LBB50_4: + RET + +TEXT ·_transpose_int16_uint64_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB51_1 + +LBB51_5: + WORD $0xd089 // mov eax, edx + LONG $0x17bf0f48 // movsx rdx, word [rdi] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + WORD $0x8948; BYTE $0x16 // mov qword [rsi], rdx + LONG $0x57bf0f48; BYTE $0x02 // movsx rdx, word [rdi + 2] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x08568948 // mov qword [rsi + 8], rdx + LONG $0x57bf0f48; BYTE $0x04 // movsx rdx, word [rdi + 4] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x10568948 // mov qword [rsi + 16], rdx + LONG $0x57bf0f48; BYTE $0x06 // movsx rdx, word [rdi + 6] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x18568948 // mov qword [rsi + 24], rdx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x08c78348 // add rdi, 8 + LONG $0x20c68348 // add rsi, 32 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB51_5 + +LBB51_1: + WORD $0xd285 // test edx, edx + JLE LBB51_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB51_3: + LONG $0x04bf0f4a; BYTE $0x07 // movsx rax, word [rdi + r8] + LONG $0x81046348 // movsxd rax, dword [rcx + 4*rax] + LONG $0x8604894a // mov qword [rsi + 4*r8], rax + LONG $0x02c08349 // add r8, 2 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB51_3 + +LBB51_4: + RET + +TEXT ·_transpose_uint32_uint64_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB52_1 + +LBB52_5: + WORD $0xd089 // mov eax, edx + WORD $0x178b // mov edx, dword [rdi] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + WORD $0x8948; BYTE $0x16 // mov qword [rsi], rdx + WORD $0x578b; BYTE $0x04 // mov edx, dword [rdi + 4] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x08568948 // mov qword [rsi + 8], rdx + WORD $0x578b; BYTE $0x08 // mov edx, dword [rdi + 8] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x10568948 // mov qword [rsi + 16], rdx + WORD $0x578b; BYTE $0x0c // mov edx, dword [rdi + 12] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x18568948 // mov qword [rsi + 24], rdx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x10c78348 // add rdi, 16 + LONG $0x20c68348 // add rsi, 32 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB52_5 + +LBB52_1: + WORD $0xd285 // test edx, edx + JLE LBB52_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB52_3: + LONG $0x07048b42 // mov eax, dword [rdi + r8] + LONG $0x81046348 // movsxd rax, dword [rcx + 4*rax] + LONG $0x4604894a // mov qword [rsi + 2*r8], rax + LONG $0x04c08349 // add r8, 4 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB52_3 + +LBB52_4: + RET + +TEXT ·_transpose_int32_uint64_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB53_1 + +LBB53_5: + WORD $0xd089 // mov eax, edx + WORD $0x6348; BYTE $0x17 // movsxd rdx, dword [rdi] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + WORD $0x8948; BYTE $0x16 // mov qword [rsi], rdx + LONG $0x04576348 // movsxd rdx, dword [rdi + 4] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x08568948 // mov qword [rsi + 8], rdx + LONG $0x08576348 // movsxd rdx, dword [rdi + 8] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x10568948 // mov qword [rsi + 16], rdx + LONG $0x0c576348 // movsxd rdx, dword [rdi + 12] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x18568948 // mov qword [rsi + 24], rdx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x10c78348 // add rdi, 16 + LONG $0x20c68348 // add rsi, 32 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB53_5 + +LBB53_1: + WORD $0xd285 // test edx, edx + JLE LBB53_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB53_3: + LONG $0x0704634a // movsxd rax, dword [rdi + r8] + LONG $0x81046348 // movsxd rax, dword [rcx + 4*rax] + LONG $0x4604894a // mov qword [rsi + 2*r8], rax + LONG $0x04c08349 // add r8, 4 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB53_3 + +LBB53_4: + RET + +TEXT ·_transpose_uint64_uint64_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB54_1 + +LBB54_5: + WORD $0xd089 // mov eax, edx + WORD $0x8b48; BYTE $0x17 // mov rdx, qword [rdi] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + WORD $0x8948; BYTE $0x16 // mov qword [rsi], rdx + LONG $0x08578b48 // mov rdx, qword [rdi + 8] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x08568948 // mov qword [rsi + 8], rdx + LONG $0x10578b48 // mov rdx, qword [rdi + 16] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x10568948 // mov qword [rsi + 16], rdx + LONG $0x18578b48 // mov rdx, qword [rdi + 24] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x18568948 // mov qword [rsi + 24], rdx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x20c78348 // add rdi, 32 + LONG $0x20c68348 // add rsi, 32 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB54_5 + +LBB54_1: + WORD $0xd285 // test edx, edx + JLE LBB54_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB54_3: + LONG $0x07048b4a // mov rax, qword [rdi + r8] + LONG $0x81046348 // movsxd rax, dword [rcx + 4*rax] + LONG $0x0604894a // mov qword [rsi + r8], rax + LONG $0x08c08349 // add r8, 8 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB54_3 + +LBB54_4: + RET + +TEXT ·_transpose_int64_uint64_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB55_1 + +LBB55_5: + WORD $0xd089 // mov eax, edx + WORD $0x8b48; BYTE $0x17 // mov rdx, qword [rdi] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + WORD $0x8948; BYTE $0x16 // mov qword [rsi], rdx + LONG $0x08578b48 // mov rdx, qword [rdi + 8] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x08568948 // mov qword [rsi + 8], rdx + LONG $0x10578b48 // mov rdx, qword [rdi + 16] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x10568948 // mov qword [rsi + 16], rdx + LONG $0x18578b48 // mov rdx, qword [rdi + 24] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x18568948 // mov qword [rsi + 24], rdx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x20c78348 // add rdi, 32 + LONG $0x20c68348 // add rsi, 32 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB55_5 + +LBB55_1: + WORD $0xd285 // test edx, edx + JLE LBB55_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB55_3: + LONG $0x07048b4a // mov rax, qword [rdi + r8] + LONG $0x81046348 // movsxd rax, dword [rcx + 4*rax] + LONG $0x0604894a // mov qword [rsi + r8], rax + LONG $0x08c08349 // add r8, 8 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB55_3 + +LBB55_4: + RET + +TEXT ·_transpose_uint8_int64_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB56_1 + +LBB56_5: + WORD $0xd089 // mov eax, edx + WORD $0xb60f; BYTE $0x17 // movzx edx, byte [rdi] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + WORD $0x8948; BYTE $0x16 // mov qword [rsi], rdx + LONG $0x0157b60f // movzx edx, byte [rdi + 1] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x08568948 // mov qword [rsi + 8], rdx + LONG $0x0257b60f // movzx edx, byte [rdi + 2] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x10568948 // mov qword [rsi + 16], rdx + LONG $0x0357b60f // movzx edx, byte [rdi + 3] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x18568948 // mov qword [rsi + 24], rdx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x04c78348 // add rdi, 4 + LONG $0x20c68348 // add rsi, 32 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB56_5 + +LBB56_1: + WORD $0xd285 // test edx, edx + JLE LBB56_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB56_3: + LONG $0x04b60f42; BYTE $0x07 // movzx eax, byte [rdi + r8] + LONG $0x81046348 // movsxd rax, dword [rcx + 4*rax] + LONG $0xc604894a // mov qword [rsi + 8*r8], rax + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB56_3 + +LBB56_4: + RET + +TEXT ·_transpose_int8_int64_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB57_1 + +LBB57_5: + WORD $0xd089 // mov eax, edx + LONG $0x17be0f48 // movsx rdx, byte [rdi] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + WORD $0x8948; BYTE $0x16 // mov qword [rsi], rdx + LONG $0x57be0f48; BYTE $0x01 // movsx rdx, byte [rdi + 1] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x08568948 // mov qword [rsi + 8], rdx + LONG $0x57be0f48; BYTE $0x02 // movsx rdx, byte [rdi + 2] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x10568948 // mov qword [rsi + 16], rdx + LONG $0x57be0f48; BYTE $0x03 // movsx rdx, byte [rdi + 3] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x18568948 // mov qword [rsi + 24], rdx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x04c78348 // add rdi, 4 + LONG $0x20c68348 // add rsi, 32 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB57_5 + +LBB57_1: + WORD $0xd285 // test edx, edx + JLE LBB57_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB57_3: + LONG $0x04be0f4a; BYTE $0x07 // movsx rax, byte [rdi + r8] + LONG $0x81046348 // movsxd rax, dword [rcx + 4*rax] + LONG $0xc604894a // mov qword [rsi + 8*r8], rax + LONG $0x01c08349 // add r8, 1 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB57_3 + +LBB57_4: + RET + +TEXT ·_transpose_uint16_int64_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB58_1 + +LBB58_5: + WORD $0xd089 // mov eax, edx + WORD $0xb70f; BYTE $0x17 // movzx edx, word [rdi] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + WORD $0x8948; BYTE $0x16 // mov qword [rsi], rdx + LONG $0x0257b70f // movzx edx, word [rdi + 2] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x08568948 // mov qword [rsi + 8], rdx + LONG $0x0457b70f // movzx edx, word [rdi + 4] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x10568948 // mov qword [rsi + 16], rdx + LONG $0x0657b70f // movzx edx, word [rdi + 6] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x18568948 // mov qword [rsi + 24], rdx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x08c78348 // add rdi, 8 + LONG $0x20c68348 // add rsi, 32 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB58_5 + +LBB58_1: + WORD $0xd285 // test edx, edx + JLE LBB58_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB58_3: + LONG $0x04b70f42; BYTE $0x07 // movzx eax, word [rdi + r8] + LONG $0x81046348 // movsxd rax, dword [rcx + 4*rax] + LONG $0x8604894a // mov qword [rsi + 4*r8], rax + LONG $0x02c08349 // add r8, 2 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB58_3 + +LBB58_4: + RET + +TEXT ·_transpose_int16_int64_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB59_1 + +LBB59_5: + WORD $0xd089 // mov eax, edx + LONG $0x17bf0f48 // movsx rdx, word [rdi] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + WORD $0x8948; BYTE $0x16 // mov qword [rsi], rdx + LONG $0x57bf0f48; BYTE $0x02 // movsx rdx, word [rdi + 2] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x08568948 // mov qword [rsi + 8], rdx + LONG $0x57bf0f48; BYTE $0x04 // movsx rdx, word [rdi + 4] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x10568948 // mov qword [rsi + 16], rdx + LONG $0x57bf0f48; BYTE $0x06 // movsx rdx, word [rdi + 6] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x18568948 // mov qword [rsi + 24], rdx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x08c78348 // add rdi, 8 + LONG $0x20c68348 // add rsi, 32 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB59_5 + +LBB59_1: + WORD $0xd285 // test edx, edx + JLE LBB59_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB59_3: + LONG $0x04bf0f4a; BYTE $0x07 // movsx rax, word [rdi + r8] + LONG $0x81046348 // movsxd rax, dword [rcx + 4*rax] + LONG $0x8604894a // mov qword [rsi + 4*r8], rax + LONG $0x02c08349 // add r8, 2 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB59_3 + +LBB59_4: + RET + +TEXT ·_transpose_uint32_int64_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB60_1 + +LBB60_5: + WORD $0xd089 // mov eax, edx + WORD $0x178b // mov edx, dword [rdi] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + WORD $0x8948; BYTE $0x16 // mov qword [rsi], rdx + WORD $0x578b; BYTE $0x04 // mov edx, dword [rdi + 4] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x08568948 // mov qword [rsi + 8], rdx + WORD $0x578b; BYTE $0x08 // mov edx, dword [rdi + 8] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x10568948 // mov qword [rsi + 16], rdx + WORD $0x578b; BYTE $0x0c // mov edx, dword [rdi + 12] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x18568948 // mov qword [rsi + 24], rdx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x10c78348 // add rdi, 16 + LONG $0x20c68348 // add rsi, 32 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB60_5 + +LBB60_1: + WORD $0xd285 // test edx, edx + JLE LBB60_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB60_3: + LONG $0x07048b42 // mov eax, dword [rdi + r8] + LONG $0x81046348 // movsxd rax, dword [rcx + 4*rax] + LONG $0x4604894a // mov qword [rsi + 2*r8], rax + LONG $0x04c08349 // add r8, 4 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB60_3 + +LBB60_4: + RET + +TEXT ·_transpose_int32_int64_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB61_1 + +LBB61_5: + WORD $0xd089 // mov eax, edx + WORD $0x6348; BYTE $0x17 // movsxd rdx, dword [rdi] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + WORD $0x8948; BYTE $0x16 // mov qword [rsi], rdx + LONG $0x04576348 // movsxd rdx, dword [rdi + 4] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x08568948 // mov qword [rsi + 8], rdx + LONG $0x08576348 // movsxd rdx, dword [rdi + 8] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x10568948 // mov qword [rsi + 16], rdx + LONG $0x0c576348 // movsxd rdx, dword [rdi + 12] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x18568948 // mov qword [rsi + 24], rdx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x10c78348 // add rdi, 16 + LONG $0x20c68348 // add rsi, 32 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB61_5 + +LBB61_1: + WORD $0xd285 // test edx, edx + JLE LBB61_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB61_3: + LONG $0x0704634a // movsxd rax, dword [rdi + r8] + LONG $0x81046348 // movsxd rax, dword [rcx + 4*rax] + LONG $0x4604894a // mov qword [rsi + 2*r8], rax + LONG $0x04c08349 // add r8, 4 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB61_3 + +LBB61_4: + RET + +TEXT ·_transpose_uint64_int64_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB62_1 + +LBB62_5: + WORD $0xd089 // mov eax, edx + WORD $0x8b48; BYTE $0x17 // mov rdx, qword [rdi] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + WORD $0x8948; BYTE $0x16 // mov qword [rsi], rdx + LONG $0x08578b48 // mov rdx, qword [rdi + 8] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x08568948 // mov qword [rsi + 8], rdx + LONG $0x10578b48 // mov rdx, qword [rdi + 16] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x10568948 // mov qword [rsi + 16], rdx + LONG $0x18578b48 // mov rdx, qword [rdi + 24] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x18568948 // mov qword [rsi + 24], rdx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x20c78348 // add rdi, 32 + LONG $0x20c68348 // add rsi, 32 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB62_5 + +LBB62_1: + WORD $0xd285 // test edx, edx + JLE LBB62_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB62_3: + LONG $0x07048b4a // mov rax, qword [rdi + r8] + LONG $0x81046348 // movsxd rax, dword [rcx + 4*rax] + LONG $0x0604894a // mov qword [rsi + r8], rax + LONG $0x08c08349 // add r8, 8 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB62_3 + +LBB62_4: + RET + +TEXT ·_transpose_int64_int64_sse4(SB), $0-32 + + MOVQ src+0(FP), DI + MOVQ dest+8(FP), SI + MOVQ length+16(FP), DX + MOVQ transposeMap+24(FP), CX + + WORD $0xfa83; BYTE $0x04 // cmp edx, 4 + JL LBB63_1 + +LBB63_5: + WORD $0xd089 // mov eax, edx + WORD $0x8b48; BYTE $0x17 // mov rdx, qword [rdi] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + WORD $0x8948; BYTE $0x16 // mov qword [rsi], rdx + LONG $0x08578b48 // mov rdx, qword [rdi + 8] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x08568948 // mov qword [rsi + 8], rdx + LONG $0x10578b48 // mov rdx, qword [rdi + 16] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x10568948 // mov qword [rsi + 16], rdx + LONG $0x18578b48 // mov rdx, qword [rdi + 24] + LONG $0x91146348 // movsxd rdx, dword [rcx + 4*rdx] + LONG $0x18568948 // mov qword [rsi + 24], rdx + WORD $0x508d; BYTE $0xfc // lea edx, [rax - 4] + LONG $0x20c78348 // add rdi, 32 + LONG $0x20c68348 // add rsi, 32 + WORD $0xf883; BYTE $0x07 // cmp eax, 7 + JG LBB63_5 + +LBB63_1: + WORD $0xd285 // test edx, edx + JLE LBB63_4 + WORD $0xc283; BYTE $0x01 // add edx, 1 + WORD $0x3145; BYTE $0xc0 // xor r8d, r8d + +LBB63_3: + LONG $0x07048b4a // mov rax, qword [rdi + r8] + LONG $0x81046348 // movsxd rax, dword [rcx + 4*rax] + LONG $0x0604894a // mov qword [rsi + r8], rax + LONG $0x08c08349 // add r8, 8 + WORD $0xc283; BYTE $0xff // add edx, -1 + WORD $0xfa83; BYTE $0x01 // cmp edx, 1 + JG LBB63_3 + +LBB63_4: + RET diff --git a/vendor/github.com/goccy/go-json/.codecov.yml b/vendor/github.com/goccy/go-json/.codecov.yml new file mode 100644 index 000000000..e98134570 --- /dev/null +++ b/vendor/github.com/goccy/go-json/.codecov.yml @@ -0,0 +1,32 @@ +codecov: + require_ci_to_pass: yes + +coverage: + precision: 2 + round: down + range: "70...100" + + status: + project: + default: + target: 70% + threshold: 2% + patch: off + changes: no + +parsers: + gcov: + branch_detection: + conditional: yes + loop: yes + method: no + macro: no + +comment: + layout: "header,diff" + behavior: default + require_changes: no + +ignore: + - internal/encoder/vm_color + - internal/encoder/vm_color_indent diff --git a/vendor/github.com/goccy/go-json/.gitignore b/vendor/github.com/goccy/go-json/.gitignore new file mode 100644 index 000000000..378283829 --- /dev/null +++ b/vendor/github.com/goccy/go-json/.gitignore @@ -0,0 +1,2 @@ +cover.html +cover.out diff --git a/vendor/github.com/goccy/go-json/.golangci.yml b/vendor/github.com/goccy/go-json/.golangci.yml new file mode 100644 index 000000000..57ae5a528 --- /dev/null +++ b/vendor/github.com/goccy/go-json/.golangci.yml @@ -0,0 +1,83 @@ +run: + skip-files: + - encode_optype.go + - ".*_test\\.go$" + +linters-settings: + govet: + enable-all: true + disable: + - shadow + +linters: + enable-all: true + disable: + - dogsled + - dupl + - exhaustive + - exhaustivestruct + - errorlint + - forbidigo + - funlen + - gci + - gochecknoglobals + - gochecknoinits + - gocognit + - gocritic + - gocyclo + - godot + - godox + - goerr113 + - gofumpt + - gomnd + - gosec + - ifshort + - lll + - makezero + - nakedret + - nestif + - nlreturn + - paralleltest + - testpackage + - thelper + - wrapcheck + - interfacer + - lll + - nakedret + - nestif + - nlreturn + - testpackage + - wsl + - varnamelen + - nilnil + - ireturn + - govet + - forcetypeassert + - cyclop + - containedctx + - revive + +issues: + exclude-rules: + # not needed + - path: /*.go + text: "ST1003: should not use underscores in package names" + linters: + - stylecheck + - path: /*.go + text: "don't use an underscore in package name" + linters: + - golint + - path: rtype.go + linters: + - golint + - stylecheck + - path: error.go + linters: + - staticcheck + + # Maximum issues count per one linter. Set to 0 to disable. Default is 50. + max-issues-per-linter: 0 + + # Maximum count of issues with the same text. Set to 0 to disable. Default is 3. + max-same-issues: 0 diff --git a/vendor/github.com/goccy/go-json/CHANGELOG.md b/vendor/github.com/goccy/go-json/CHANGELOG.md new file mode 100644 index 000000000..d09bb89c3 --- /dev/null +++ b/vendor/github.com/goccy/go-json/CHANGELOG.md @@ -0,0 +1,425 @@ +# v0.10.2 - 2023/03/20 + +### New features + +* Support DebugDOT option for debugging encoder ( #440 ) + +### Fix bugs + +* Fix combination of embedding structure and omitempty option ( #442 ) + +# v0.10.1 - 2023/03/13 + +### Fix bugs + +* Fix checkptr error for array decoder ( #415 ) +* Fix added buffer size check when decoding key ( #430 ) +* Fix handling of anonymous fields other than struct ( #431 ) +* Fix to not optimize when lower conversion can't handle byte-by-byte ( #432 ) +* Fix a problem that MarshalIndent does not work when UnorderedMap is specified ( #435 ) +* Fix mapDecoder.DecodeStream() for empty objects containing whitespace ( #425 ) +* Fix an issue that could not set the correct NextField for fields in the embedded structure ( #438 ) + +# v0.10.0 - 2022/11/29 + +### New features + +* Support JSON Path ( #250 ) + +### Fix bugs + +* Fix marshaler for map's key ( #409 ) + +# v0.9.11 - 2022/08/18 + +### Fix bugs + +* Fix unexpected behavior when buffer ends with backslash ( #383 ) +* Fix stream decoding of escaped character ( #387 ) + +# v0.9.10 - 2022/07/15 + +### Fix bugs + +* Fix boundary exception of type caching ( #382 ) + +# v0.9.9 - 2022/07/15 + +### Fix bugs + +* Fix encoding of directed interface with typed nil ( #377 ) +* Fix embedded primitive type encoding using alias ( #378 ) +* Fix slice/array type encoding with types implementing MarshalJSON ( #379 ) +* Fix unicode decoding when the expected buffer state is not met after reading ( #380 ) + +# v0.9.8 - 2022/06/30 + +### Fix bugs + +* Fix decoding of surrogate-pair ( #365 ) +* Fix handling of embedded primitive type ( #366 ) +* Add validation of escape sequence for decoder ( #367 ) +* Fix stream tokenizing respecting UseNumber ( #369 ) +* Fix encoding when struct pointer type that implements Marshal JSON is embedded ( #375 ) + +### Improve performance + +* Improve performance of linkRecursiveCode ( #368 ) + +# v0.9.7 - 2022/04/22 + +### Fix bugs + +#### Encoder + +* Add filtering process for encoding on slow path ( #355 ) +* Fix encoding of interface{} with pointer type ( #363 ) + +#### Decoder + +* Fix map key decoder that implements UnmarshalJSON ( #353 ) +* Fix decoding of []uint8 type ( #361 ) + +### New features + +* Add DebugWith option for encoder ( #356 ) + +# v0.9.6 - 2022/03/22 + +### Fix bugs + +* Correct the handling of the minimum value of int type for decoder ( #344 ) +* Fix bugs of stream decoder's bufferSize ( #349 ) +* Add a guard to use typeptr more safely ( #351 ) + +### Improve decoder performance + +* Improve escapeString's performance ( #345 ) + +### Others + +* Update go version for CI ( #347 ) + +# v0.9.5 - 2022/03/04 + +### Fix bugs + +* Fix panic when decoding time.Time with context ( #328 ) +* Fix reading the next character in buffer to nul consideration ( #338 ) +* Fix incorrect handling on skipValue ( #341 ) + +### Improve decoder performance + +* Improve performance when a payload contains escape sequence ( #334 ) + +# v0.9.4 - 2022/01/21 + +* Fix IsNilForMarshaler for string type with omitempty ( #323 ) +* Fix the case where the embedded field is at the end ( #326 ) + +# v0.9.3 - 2022/01/14 + +* Fix logic of removing struct field for decoder ( #322 ) + +# v0.9.2 - 2022/01/14 + +* Add invalid decoder to delay type error judgment at decode ( #321 ) + +# v0.9.1 - 2022/01/11 + +* Fix encoding of MarshalText/MarshalJSON operation with head offset ( #319 ) + +# v0.9.0 - 2022/01/05 + +### New feature + +* Supports dynamic filtering of struct fields ( #314 ) + +### Improve encoding performance + +* Improve map encoding performance ( #310 ) +* Optimize encoding path for escaped string ( #311 ) +* Add encoding option for performance ( #312 ) + +### Fix bugs + +* Fix panic at encoding map value on 1.18 ( #310 ) +* Fix MarshalIndent for interface type ( #317 ) + +# v0.8.1 - 2021/12/05 + +* Fix operation conversion from PtrHead to Head in Recursive type ( #305 ) + +# v0.8.0 - 2021/12/02 + +* Fix embedded field conflict behavior ( #300 ) +* Refactor compiler for encoder ( #301 #302 ) + +# v0.7.10 - 2021/10/16 + +* Fix conversion from pointer to uint64 ( #294 ) + +# v0.7.9 - 2021/09/28 + +* Fix encoding of nil value about interface type that has method ( #291 ) + +# v0.7.8 - 2021/09/01 + +* Fix mapassign_faststr for indirect struct type ( #283 ) +* Fix encoding of not empty interface type ( #284 ) +* Fix encoding of empty struct interface type ( #286 ) + +# v0.7.7 - 2021/08/25 + +* Fix invalid utf8 on stream decoder ( #279 ) +* Fix buffer length bug on string stream decoder ( #280 ) + +Thank you @orisano !! + +# v0.7.6 - 2021/08/13 + +* Fix nil slice assignment ( #276 ) +* Improve error message ( #277 ) + +# v0.7.5 - 2021/08/12 + +* Fix encoding of embedded struct with tags ( #265 ) +* Fix encoding of embedded struct that isn't first field ( #272 ) +* Fix decoding of binary type with escaped char ( #273 ) + +# v0.7.4 - 2021/07/06 + +* Fix encoding of indirect layout structure ( #264 ) + +# v0.7.3 - 2021/06/29 + +* Fix encoding of pointer type in empty interface ( #262 ) + +# v0.7.2 - 2021/06/26 + +### Fix decoder + +* Add decoder for func type to fix decoding of nil function value ( #257 ) +* Fix stream decoding of []byte type ( #258 ) + +### Performance + +* Improve decoding performance of map[string]interface{} type ( use `mapassign_faststr` ) ( #256 ) +* Improve encoding performance of empty interface type ( remove recursive calling of `vm.Run` ) ( #259 ) + +### Benchmark + +* Add bytedance/sonic as benchmark target ( #254 ) + +# v0.7.1 - 2021/06/18 + +### Fix decoder + +* Fix error when unmarshal empty array ( #253 ) + +# v0.7.0 - 2021/06/12 + +### Support context for MarshalJSON and UnmarshalJSON ( #248 ) + +* json.MarshalContext(context.Context, interface{}, ...json.EncodeOption) ([]byte, error) +* json.NewEncoder(io.Writer).EncodeContext(context.Context, interface{}, ...json.EncodeOption) error +* json.UnmarshalContext(context.Context, []byte, interface{}, ...json.DecodeOption) error +* json.NewDecoder(io.Reader).DecodeContext(context.Context, interface{}) error + +```go +type MarshalerContext interface { + MarshalJSON(context.Context) ([]byte, error) +} + +type UnmarshalerContext interface { + UnmarshalJSON(context.Context, []byte) error +} +``` + +### Add DecodeFieldPriorityFirstWin option ( #242 ) + +In the default behavior, go-json, like encoding/json, will reflect the result of the last evaluation when a field with the same name exists. I've added new options to allow you to change this behavior. `json.DecodeFieldPriorityFirstWin` option reflects the result of the first evaluation if a field with the same name exists. This behavior has a performance advantage as it allows the subsequent strings to be skipped if all fields have been evaluated. + +### Fix encoder + +* Fix indent number contains recursive type ( #249 ) +* Fix encoding of using empty interface as map key ( #244 ) + +### Fix decoder + +* Fix decoding fields containing escaped characters ( #237 ) + +### Refactor + +* Move some tests to subdirectory ( #243 ) +* Refactor package layout for decoder ( #238 ) + +# v0.6.1 - 2021/06/02 + +### Fix encoder + +* Fix value of totalLength for encoding ( #236 ) + +# v0.6.0 - 2021/06/01 + +### Support Colorize option for encoding (#233) + +```go +b, err := json.MarshalWithOption(v, json.Colorize(json.DefaultColorScheme)) +if err != nil { + ... +} +fmt.Println(string(b)) // print colored json +``` + +### Refactor + +* Fix opcode layout - Adjust memory layout of the opcode to 128 bytes in a 64-bit environment ( #230 ) +* Refactor encode option ( #231 ) +* Refactor escape string ( #232 ) + +# v0.5.1 - 2021/5/20 + +### Optimization + +* Add type addrShift to enable bigger encoder/decoder cache ( #213 ) + +### Fix decoder + +* Keep original reference of slice element ( #229 ) + +### Refactor + +* Refactor Debug mode for encoding ( #226 ) +* Generate VM sources for encoding ( #227 ) +* Refactor validator for null/true/false for decoding ( #221 ) + +# v0.5.0 - 2021/5/9 + +### Supports using omitempty and string tags at the same time ( #216 ) + +### Fix decoder + +* Fix stream decoder for unicode char ( #215 ) +* Fix decoding of slice element ( #219 ) +* Fix calculating of buffer length for stream decoder ( #220 ) + +### Refactor + +* replace skipWhiteSpace goto by loop ( #212 ) + +# v0.4.14 - 2021/5/4 + +### Benchmark + +* Add valyala/fastjson to benchmark ( #193 ) +* Add benchmark task for CI ( #211 ) + +### Fix decoder + +* Fix decoding of slice with unmarshal json type ( #198 ) +* Fix decoding of null value for interface type that does not implement Unmarshaler ( #205 ) +* Fix decoding of null value to []byte by json.Unmarshal ( #206 ) +* Fix decoding of backslash char at the end of string ( #207 ) +* Fix stream decoder for null/true/false value ( #208 ) +* Fix stream decoder for slow reader ( #211 ) + +### Performance + +* If cap of slice is enough, reuse slice data for compatibility with encoding/json ( #200 ) + +# v0.4.13 - 2021/4/20 + +### Fix json.Compact and json.Indent + +* Support validation the input buffer for json.Compact and json.Indent ( #189 ) +* Optimize json.Compact and json.Indent ( improve memory footprint ) ( #190 ) + +# v0.4.12 - 2021/4/15 + +### Fix encoder + +* Fix unnecessary indent for empty slice type ( #181 ) +* Fix encoding of omitempty feature for the slice or interface type ( #183 ) +* Fix encoding custom types zero values with omitempty when marshaller exists ( #187 ) + +### Fix decoder + +* Fix decoder for invalid top level value ( #184 ) +* Fix decoder for invalid number value ( #185 ) + +# v0.4.11 - 2021/4/3 + +* Improve decoder performance for interface type + +# v0.4.10 - 2021/4/2 + +### Fix encoder + +* Fixed a bug when encoding slice and map containing recursive structures +* Fixed a logic to determine if indirect reference + +# v0.4.9 - 2021/3/29 + +### Add debug mode + +If you use `json.MarshalWithOption(v, json.Debug())` and `panic` occurred in `go-json`, produces debug information to console. + +### Support a new feature to compatible with encoding/json + +- invalid UTF-8 is coerced to valid UTF-8 ( without performance down ) + +### Fix encoder + +- Fixed handling of MarshalJSON of function type + +### Fix decoding of slice of pointer type + +If there is a pointer value, go-json will use it. (This behavior is necessary to achieve the ability to prioritize pre-filled values). However, since slices are reused internally, there was a bug that referred to the previous pointer value. Therefore, it is not necessary to refer to the pointer value in advance for the slice element, so we explicitly initialize slice element by `nil`. + +# v0.4.8 - 2021/3/21 + +### Reduce memory usage at compile time + +* go-json have used about 2GB of memory at compile time, but now it can compile with about less than 550MB. + +### Fix any encoder's bug + +* Add many test cases for encoder +* Fix composite type ( slice/array/map ) +* Fix pointer types +* Fix encoding of MarshalJSON or MarshalText or json.Number type + +### Refactor encoder + +* Change package layout for reducing memory usage at compile +* Remove anonymous and only operation +* Remove root property from encodeCompileContext and opcode + +### Fix CI + +* Add Go 1.16 +* Remove Go 1.13 +* Fix `make cover` task + +### Number/Delim/Token/RawMessage use the types defined in encoding/json by type alias + +# v0.4.7 - 2021/02/22 + +### Fix decoder + +* Fix decoding of deep recursive structure +* Fix decoding of embedded unexported pointer field +* Fix invalid test case +* Fix decoding of invalid value +* Fix decoding of prefilled value +* Fix not being able to return UnmarshalTypeError when it should be returned +* Fix decoding of null value +* Fix decoding of type of null string +* Use pre allocated pointer if exists it at decoding + +### Reduce memory usage at compile + +* Integrate int/int8/int16/int32/int64 and uint/uint8/uint16/uint32/uint64 operation to reduce memory usage at compile + +### Remove unnecessary optype diff --git a/vendor/github.com/goccy/go-json/LICENSE b/vendor/github.com/goccy/go-json/LICENSE new file mode 100644 index 000000000..6449c8bff --- /dev/null +++ b/vendor/github.com/goccy/go-json/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Masaaki Goshima + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/goccy/go-json/Makefile b/vendor/github.com/goccy/go-json/Makefile new file mode 100644 index 000000000..5bbfc4c9a --- /dev/null +++ b/vendor/github.com/goccy/go-json/Makefile @@ -0,0 +1,39 @@ +PKG := github.com/goccy/go-json + +BIN_DIR := $(CURDIR)/bin +PKGS := $(shell go list ./... | grep -v internal/cmd|grep -v test) +COVER_PKGS := $(foreach pkg,$(PKGS),$(subst $(PKG),.,$(pkg))) + +COMMA := , +EMPTY := +SPACE := $(EMPTY) $(EMPTY) +COVERPKG_OPT := $(subst $(SPACE),$(COMMA),$(COVER_PKGS)) + +$(BIN_DIR): + @mkdir -p $(BIN_DIR) + +.PHONY: cover +cover: + go test -coverpkg=$(COVERPKG_OPT) -coverprofile=cover.out ./... + +.PHONY: cover-html +cover-html: cover + go tool cover -html=cover.out + +.PHONY: lint +lint: golangci-lint + $(BIN_DIR)/golangci-lint run + +golangci-lint: | $(BIN_DIR) + @{ \ + set -e; \ + GOLANGCI_LINT_TMP_DIR=$$(mktemp -d); \ + cd $$GOLANGCI_LINT_TMP_DIR; \ + go mod init tmp; \ + GOBIN=$(BIN_DIR) go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.48.0; \ + rm -rf $$GOLANGCI_LINT_TMP_DIR; \ + } + +.PHONY: generate +generate: + go generate ./internal/... diff --git a/vendor/github.com/goccy/go-json/README.md b/vendor/github.com/goccy/go-json/README.md new file mode 100644 index 000000000..7bacc54f9 --- /dev/null +++ b/vendor/github.com/goccy/go-json/README.md @@ -0,0 +1,529 @@ +# go-json + +![Go](https://github.com/goccy/go-json/workflows/Go/badge.svg) +[![GoDoc](https://godoc.org/github.com/goccy/go-json?status.svg)](https://pkg.go.dev/github.com/goccy/go-json?tab=doc) +[![codecov](https://codecov.io/gh/goccy/go-json/branch/master/graph/badge.svg)](https://codecov.io/gh/goccy/go-json) + +Fast JSON encoder/decoder compatible with encoding/json for Go + + + +# Roadmap + +``` +* version ( expected release date ) + +* v0.9.0 + | + | while maintaining compatibility with encoding/json, we will add convenient APIs + | + v +* v1.0.0 +``` + +We are accepting requests for features that will be implemented between v0.9.0 and v.1.0.0. +If you have the API you need, please submit your issue [here](https://github.com/goccy/go-json/issues). + +# Features + +- Drop-in replacement of `encoding/json` +- Fast ( See [Benchmark section](https://github.com/goccy/go-json#benchmarks) ) +- Flexible customization with options +- Coloring the encoded string +- Can propagate context.Context to `MarshalJSON` or `UnmarshalJSON` +- Can dynamically filter the fields of the structure type-safely + +# Installation + +``` +go get github.com/goccy/go-json +``` + +# How to use + +Replace import statement from `encoding/json` to `github.com/goccy/go-json` + +``` +-import "encoding/json" ++import "github.com/goccy/go-json" +``` + +# JSON library comparison + +| name | encoder | decoder | compatible with `encoding/json` | +| :----: | :------: | :-----: | :-----------------------------: | +| encoding/json | yes | yes | N/A | +| [json-iterator/go](https://github.com/json-iterator/go) | yes | yes | partial | +| [easyjson](https://github.com/mailru/easyjson) | yes | yes | no | +| [gojay](https://github.com/francoispqt/gojay) | yes | yes | no | +| [segmentio/encoding/json](https://github.com/segmentio/encoding/tree/master/json) | yes | yes | partial | +| [jettison](https://github.com/wI2L/jettison) | yes | no | no | +| [simdjson-go](https://github.com/minio/simdjson-go) | no | yes | no | +| goccy/go-json | yes | yes | yes | + +- `json-iterator/go` isn't compatible with `encoding/json` in many ways (e.g. https://github.com/json-iterator/go/issues/229 ), but it hasn't been supported for a long time. +- `segmentio/encoding/json` is well supported for encoders, but some are not supported for decoder APIs such as `Token` ( streaming decode ) + +## Other libraries + +- [jingo](https://github.com/bet365/jingo) + +I tried the benchmark but it didn't work. +Also, it seems to panic when it receives an unexpected value because there is no error handling... + +- [ffjson](https://github.com/pquerna/ffjson) + +Benchmarking gave very slow results. +It seems that it is assumed that the user will use the buffer pool properly. +Also, development seems to have already stopped + +# Benchmarks + +``` +$ cd benchmarks +$ go test -bench . +``` + +## Encode + + + + +## Decode + + + + + + +# Fuzzing + +[go-json-fuzz](https://github.com/goccy/go-json-fuzz) is the repository for fuzzing tests. +If you run the test in this repository and find a bug, please commit to corpus to go-json-fuzz and report the issue to [go-json](https://github.com/goccy/go-json/issues). + +# How it works + +`go-json` is very fast in both encoding and decoding compared to other libraries. +It's easier to implement by using automatic code generation for performance or by using a dedicated interface, but `go-json` dares to stick to compatibility with `encoding/json` and is the simple interface. Despite this, we are developing with the aim of being the fastest library. + +Here, we explain the various speed-up techniques implemented by `go-json`. + +## Basic technique + +The techniques listed here are the ones used by most of the libraries listed above. + +### Buffer reuse + +Since the only value required for the result of `json.Marshal(interface{}) ([]byte, error)` is `[]byte`, the only value that must be allocated during encoding is the return value `[]byte` . + +Also, as the number of allocations increases, the performance will be affected, so the number of allocations should be kept as low as possible when creating `[]byte`. + +Therefore, there is a technique to reduce the number of times a new buffer must be allocated by reusing the buffer used for the previous encoding by using `sync.Pool`. + +Finally, you allocate a buffer that is as long as the resulting buffer and copy the contents into it, you only need to allocate the buffer once in theory. + +```go +type buffer struct { + data []byte +} + +var bufPool = sync.Pool{ + New: func() interface{} { + return &buffer{data: make([]byte, 0, 1024)} + }, +} + +buf := bufPool.Get().(*buffer) +data := encode(buf.data) // reuse buf.data + +newBuf := make([]byte, len(data)) +copy(newBuf, buf) + +buf.data = data +bufPool.Put(buf) +``` + +### Elimination of reflection + +As you know, the reflection operation is very slow. + +Therefore, using the fact that the address position where the type information is stored is fixed for each binary ( we call this `typeptr` ), +we can use the address in the type information to call a pre-built optimized process. + +For example, you can get the address to the type information from `interface{}` as follows and you can use that information to call a process that does not have reflection. + +To process without reflection, pass a pointer (`unsafe.Pointer`) to the value is stored. + +```go + +type emptyInterface struct { + typ unsafe.Pointer + ptr unsafe.Pointer +} + +var typeToEncoder = map[uintptr]func(unsafe.Pointer)([]byte, error){} + +func Marshal(v interface{}) ([]byte, error) { + iface := (*emptyInterface)(unsafe.Pointer(&v) + typeptr := uintptr(iface.typ) + if enc, exists := typeToEncoder[typeptr]; exists { + return enc(iface.ptr) + } + ... +} +``` + +※ In reality, `typeToEncoder` can be referenced by multiple goroutines, so exclusive control is required. + +## Unique speed-up technique + +## Encoder + +### Do not escape arguments of `Marshal` + +`json.Marshal` and `json.Unmarshal` receive `interface{}` value and they perform type determination dynamically to process. +In normal case, you need to use the `reflect` library to determine the type dynamically, but since `reflect.Type` is defined as `interface`, when you call the method of `reflect.Type`, The reflect's argument is escaped. + +Therefore, the arguments for `Marshal` and `Unmarshal` are always escaped to the heap. +However, `go-json` can use the feature of `reflect.Type` while avoiding escaping. + +`reflect.Type` is defined as `interface`, but in reality `reflect.Type` is implemented only by the structure `rtype` defined in the `reflect` package. +For this reason, to date `reflect.Type` is the same as `*reflect.rtype`. + +Therefore, by directly handling `*reflect.rtype`, which is an implementation of `reflect.Type`, it is possible to avoid escaping because it changes from `interface` to using `struct`. + +The technique for working with `*reflect.rtype` directly from `go-json` is implemented at [rtype.go](https://github.com/goccy/go-json/blob/master/internal/runtime/rtype.go) + +Also, the same technique is cut out as a library ( https://github.com/goccy/go-reflect ) + +Initially this feature was the default behavior of `go-json`. +But after careful testing, I found that I passed a large value to `json.Marshal()` and if the argument could not be assigned to the stack, it could not be properly escaped to the heap (a bug in the Go compiler). + +Therefore, this feature will be provided as an **optional** until this issue is resolved. + +To use it, add `NoEscape` like `MarshalNoEscape()` + +### Encoding using opcode sequence + +I explained that you can use `typeptr` to call a pre-built process from type information. + +In other libraries, this dedicated process is processed by making it an function calling like anonymous function, but function calls are inherently slow processes and should be avoided as much as possible. + +Therefore, `go-json` adopted the Instruction-based execution processing system, which is also used to implement virtual machines for programming language. + +If it is the first type to encode, create the opcode ( instruction ) sequence required for encoding. +From the second time onward, use `typeptr` to get the cached pre-built opcode sequence and encode it based on it. An example of the opcode sequence is shown below. + +```go +json.Marshal(struct{ + X int `json:"x"` + Y string `json:"y"` +}{X: 1, Y: "hello"}) +``` + +When encoding a structure like the one above, create a sequence of opcodes like this: + +``` +- opStructFieldHead ( `{` ) +- opStructFieldInt ( `"x": 1,` ) +- opStructFieldString ( `"y": "hello"` ) +- opStructEnd ( `}` ) +- opEnd +``` + +※ When processing each operation, write the letters on the right. + +In addition, each opcode is managed by the following structure ( +Pseudo code ). + +```go +type opType int +const ( + opStructFieldHead opType = iota + opStructFieldInt + opStructFieldStirng + opStructEnd + opEnd +) +type opcode struct { + op opType + key []byte + next *opcode +} +``` + +The process of encoding using the opcode sequence is roughly implemented as follows. + +```go +func encode(code *opcode, b []byte, p unsafe.Pointer) ([]byte, error) { + for { + switch code.op { + case opStructFieldHead: + b = append(b, '{') + code = code.next + case opStructFieldInt: + b = append(b, code.key...) + b = appendInt((*int)(unsafe.Pointer(uintptr(p)+code.offset))) + code = code.next + case opStructFieldString: + b = append(b, code.key...) + b = appendString((*string)(unsafe.Pointer(uintptr(p)+code.offset))) + code = code.next + case opStructEnd: + b = append(b, '}') + code = code.next + case opEnd: + goto END + } + } +END: + return b, nil +} +``` + +In this way, the huge `switch-case` is used to encode by manipulating the linked list opcodes to avoid unnecessary function calls. + +### Opcode sequence optimization + +One of the advantages of encoding using the opcode sequence is the ease of optimization. +The opcode sequence mentioned above is actually converted into the following optimized operations and used. + +``` +- opStructFieldHeadInt ( `{"x": 1,` ) +- opStructEndString ( `"y": "hello"}` ) +- opEnd +``` + +It has been reduced from 5 opcodes to 3 opcodes ! +Reducing the number of opcodees means reducing the number of branches with `switch-case`. +In other words, the closer the number of operations is to 1, the faster the processing can be performed. + +In `go-json`, optimization to reduce the number of opcodes itself like the above and it speeds up by preparing opcodes with optimized paths. + +### Change recursive call from CALL to JMP + +Recursive processing is required during encoding if the type is defined recursively as follows: + +```go +type T struct { + X int + U *U +} + +type U struct { + T *T +} + +b, err := json.Marshal(&T{ + X: 1, + U: &U{ + T: &T{ + X: 2, + }, + }, +}) +fmt.Println(string(b)) // {"X":1,"U":{"T":{"X":2,"U":null}}} +``` + +In `go-json`, recursive processing is processed by the operation type of ` opStructFieldRecursive`. + +In this operation, after acquiring the opcode sequence used for recursive processing, the function is **not** called recursively as it is, but the necessary values ​​are saved by itself and implemented by moving to the next operation. + +The technique of implementing recursive processing with the `JMP` operation while avoiding the `CALL` operation is a famous technique for implementing a high-speed virtual machine. + +For more details, please refer to [the article](https://engineering.mercari.com/blog/entry/1599563768-081104c850) ( but Japanese only ). + +### Dispatch by typeptr from map to slice + +When retrieving the data cached from the type information by `typeptr`, we usually use map. +Map requires exclusive control, so use `sync.Map` for a naive implementation. + +However, this is slow, so it's a good idea to use the `atomic` package for exclusive control as implemented by `segmentio/encoding/json` ( https://github.com/segmentio/encoding/blob/master/json/codec.go#L41-L55 ). + +This implementation slows down the set instead of speeding up the get, but it works well because of the nature of the library, it encodes much more for the same type. + +However, as a result of profiling, I noticed that `runtime.mapaccess2` accounts for a significant percentage of the execution time. So I thought if I could change the lookup from map to slice. + +There is an API named `typelinks` defined in the `runtime` package that the `reflect` package uses internally. +This allows you to get all the type information defined in the binary at runtime. + +The fact that all type information can be acquired means that by constructing slices in advance with the acquired total number of type information, it is possible to look up with the value of `typeptr` without worrying about out-of-range access. + +However, if there is too much type information, it will use a lot of memory, so by default we will only use this optimization if the slice size fits within **2Mib** . + +If this approach is not available, it will fall back to the `atomic` based process described above. + +If you want to know more, please refer to the implementation [here](https://github.com/goccy/go-json/blob/master/internal/runtime/type.go#L36-L100) + +## Decoder + +### Dispatch by typeptr from map to slice + +Like the encoder, the decoder also uses typeptr to call the dedicated process. + +### Faster termination character inspection using NUL character + +In order to decode, you have to traverse the input buffer character by position. +At that time, if you check whether the buffer has reached the end, it will be very slow. + +`buf` : `[]byte` type variable. holds the string passed to the decoder +`cursor` : `int64` type variable. holds the current read position + +```go +buflen := len(buf) +for ; cursor < buflen; cursor++ { // compare cursor and buflen at all times, it is so slow. + switch buf[cursor] { + case ' ', '\n', '\r', '\t': + } +} +``` + +Therefore, by adding the `NUL` (`\000`) character to the end of the read buffer as shown below, it is possible to check the termination character at the same time as other characters. + +```go +for { + switch buf[cursor] { + case ' ', '\n', '\r', '\t': + case '\000': + return nil + } + cursor++ +} +``` + +### Use Boundary Check Elimination + +Due to the `NUL` character optimization, the Go compiler does a boundary check every time, even though `buf[cursor]` does not cause out-of-range access. + +Therefore, `go-json` eliminates boundary check by fetching characters for hotspot by pointer operation. For example, the following code. + +```go +func char(ptr unsafe.Pointer, offset int64) byte { + return *(*byte)(unsafe.Pointer(uintptr(ptr) + uintptr(offset))) +} + +p := (*sliceHeader)(&unsafe.Pointer(buf)).data +for { + switch char(p, cursor) { + case ' ', '\n', '\r', '\t': + case '\000': + return nil + } + cursor++ +} +``` + +### Checking the existence of fields of struct using Bitmaps + +I found by the profiling result, in the struct decode, lookup process for field was taking a long time. + +For example, consider decoding a string like `{"a":1,"b":2,"c":3}` into the following structure: + +```go +type T struct { + A int `json:"a"` + B int `json:"b"` + C int `json:"c"` +} +``` + +At this time, it was found that it takes a lot of time to acquire the decoding process corresponding to the field from the field name as shown below during the decoding process. + +```go +fieldName := decodeKey(buf, cursor) // "a" or "b" or "c" +decoder, exists := fieldToDecoderMap[fieldName] // so slow +if exists { + decoder(buf, cursor) +} else { + skipValue(buf, cursor) +} +``` + +To improve this process, `json-iterator/go` is optimized so that it can be branched by switch-case when the number of fields in the structure is 10 or less (switch-case is faster than map). However, there is a risk of hash collision because the value hashed by the FNV algorithm is used for conditional branching. Also, `gojay` processes this part at high speed by letting the library user yourself write `switch-case`. + + +`go-json` considers and implements a new approach that is different from these. I call this **bitmap field optimization**. + +The range of values ​​per character can be represented by `[256]byte`. Also, if the number of fields in the structure is 8 or less, `int8` type can represent the state of each field. +In other words, it has the following structure. + +- Base ( 8bit ): `00000000` +- Key "a": `00000001` ( assign key "a" to the first bit ) +- Key "b": `00000010` ( assign key "b" to the second bit ) +- Key "c": `00000100` ( assign key "c" to the third bit ) + +Bitmap structure is the following + +``` + | key index(0) | +------------------------ + 0 | 00000000 | + 1 | 00000000 | +~~ | | +97 (a) | 00000001 | +98 (b) | 00000010 | +99 (c) | 00000100 | +~~ | | +255 | 00000000 | +``` + +You can think of this as a Bitmap with a height of `256` and a width of the maximum string length in the field name. +In other words, it can be represented by the following type . + +```go +[maxFieldKeyLength][256]int8 +``` + +When decoding a field character, check whether the corresponding character exists by referring to the pre-built bitmap like the following. + +```go +var curBit int8 = math.MaxInt8 // 11111111 + +c := char(buf, cursor) +bit := bitmap[keyIdx][c] +curBit &= bit +if curBit == 0 { + // not found field +} +``` + +If `curBit` is not `0` until the end of the field string, then the string is +You may have hit one of the fields. +But the possibility is that if the decoded string is shorter than the field string, you will get a false hit. + +- input: `{"a":1}` +```go +type T struct { + X int `json:"abc"` +} +``` +※ Since `a` is shorter than `abc`, it can decode to the end of the field character without `curBit` being 0. + +Rest assured. In this case, it doesn't matter because you can tell if you hit by comparing the string length of `a` with the string length of `abc`. + +Finally, calculate the position of the bit where `1` is set and get the corresponding value, and you're done. + +Using this technique, field lookups are possible with only bitwise operations and access to slices. + +`go-json` uses a similar technique for fields with 9 or more and 16 or less fields. At this time, Bitmap is constructed as `[maxKeyLen][256]int16` type. + +Currently, this optimization is not performed when the maximum length of the field name is long (specifically, 64 bytes or more) in addition to the limitation of the number of fields from the viewpoint of saving memory usage. + +### Others + +I have done a lot of other optimizations. I will find time to write about them. If you have any questions about what's written here or other optimizations, please visit the `#go-json` channel on `gophers.slack.com` . + +## Reference + +Regarding the story of go-json, there are the following articles in Japanese only. + +- https://speakerdeck.com/goccy/zui-su-falsejsonraiburariwoqiu-mete +- https://engineering.mercari.com/blog/entry/1599563768-081104c850/ + +# Looking for Sponsors + +I'm looking for sponsors this library. This library is being developed as a personal project in my spare time. If you want a quick response or problem resolution when using this library in your project, please register as a [sponsor](https://github.com/sponsors/goccy). I will cooperate as much as possible. Of course, this library is developed as an MIT license, so you can use it freely for free. + +# License + +MIT diff --git a/vendor/github.com/goccy/go-json/color.go b/vendor/github.com/goccy/go-json/color.go new file mode 100644 index 000000000..e80b22b48 --- /dev/null +++ b/vendor/github.com/goccy/go-json/color.go @@ -0,0 +1,68 @@ +package json + +import ( + "fmt" + + "github.com/goccy/go-json/internal/encoder" +) + +type ( + ColorFormat = encoder.ColorFormat + ColorScheme = encoder.ColorScheme +) + +const escape = "\x1b" + +type colorAttr int + +//nolint:deadcode,varcheck +const ( + fgBlackColor colorAttr = iota + 30 + fgRedColor + fgGreenColor + fgYellowColor + fgBlueColor + fgMagentaColor + fgCyanColor + fgWhiteColor +) + +//nolint:deadcode,varcheck +const ( + fgHiBlackColor colorAttr = iota + 90 + fgHiRedColor + fgHiGreenColor + fgHiYellowColor + fgHiBlueColor + fgHiMagentaColor + fgHiCyanColor + fgHiWhiteColor +) + +func createColorFormat(attr colorAttr) ColorFormat { + return ColorFormat{ + Header: wrapColor(attr), + Footer: resetColor(), + } +} + +func wrapColor(attr colorAttr) string { + return fmt.Sprintf("%s[%dm", escape, attr) +} + +func resetColor() string { + return wrapColor(colorAttr(0)) +} + +var ( + DefaultColorScheme = &ColorScheme{ + Int: createColorFormat(fgHiMagentaColor), + Uint: createColorFormat(fgHiMagentaColor), + Float: createColorFormat(fgHiMagentaColor), + Bool: createColorFormat(fgHiYellowColor), + String: createColorFormat(fgHiGreenColor), + Binary: createColorFormat(fgHiRedColor), + ObjectKey: createColorFormat(fgHiCyanColor), + Null: createColorFormat(fgBlueColor), + } +) diff --git a/vendor/github.com/goccy/go-json/decode.go b/vendor/github.com/goccy/go-json/decode.go new file mode 100644 index 000000000..74c6ac3bc --- /dev/null +++ b/vendor/github.com/goccy/go-json/decode.go @@ -0,0 +1,263 @@ +package json + +import ( + "context" + "fmt" + "io" + "reflect" + "unsafe" + + "github.com/goccy/go-json/internal/decoder" + "github.com/goccy/go-json/internal/errors" + "github.com/goccy/go-json/internal/runtime" +) + +type Decoder struct { + s *decoder.Stream +} + +const ( + nul = '\000' +) + +type emptyInterface struct { + typ *runtime.Type + ptr unsafe.Pointer +} + +func unmarshal(data []byte, v interface{}, optFuncs ...DecodeOptionFunc) error { + src := make([]byte, len(data)+1) // append nul byte to the end + copy(src, data) + + header := (*emptyInterface)(unsafe.Pointer(&v)) + + if err := validateType(header.typ, uintptr(header.ptr)); err != nil { + return err + } + dec, err := decoder.CompileToGetDecoder(header.typ) + if err != nil { + return err + } + ctx := decoder.TakeRuntimeContext() + ctx.Buf = src + ctx.Option.Flags = 0 + for _, optFunc := range optFuncs { + optFunc(ctx.Option) + } + cursor, err := dec.Decode(ctx, 0, 0, header.ptr) + if err != nil { + decoder.ReleaseRuntimeContext(ctx) + return err + } + decoder.ReleaseRuntimeContext(ctx) + return validateEndBuf(src, cursor) +} + +func unmarshalContext(ctx context.Context, data []byte, v interface{}, optFuncs ...DecodeOptionFunc) error { + src := make([]byte, len(data)+1) // append nul byte to the end + copy(src, data) + + header := (*emptyInterface)(unsafe.Pointer(&v)) + + if err := validateType(header.typ, uintptr(header.ptr)); err != nil { + return err + } + dec, err := decoder.CompileToGetDecoder(header.typ) + if err != nil { + return err + } + rctx := decoder.TakeRuntimeContext() + rctx.Buf = src + rctx.Option.Flags = 0 + rctx.Option.Flags |= decoder.ContextOption + rctx.Option.Context = ctx + for _, optFunc := range optFuncs { + optFunc(rctx.Option) + } + cursor, err := dec.Decode(rctx, 0, 0, header.ptr) + if err != nil { + decoder.ReleaseRuntimeContext(rctx) + return err + } + decoder.ReleaseRuntimeContext(rctx) + return validateEndBuf(src, cursor) +} + +var ( + pathDecoder = decoder.NewPathDecoder() +) + +func extractFromPath(path *Path, data []byte, optFuncs ...DecodeOptionFunc) ([][]byte, error) { + if path.path.RootSelectorOnly { + return [][]byte{data}, nil + } + src := make([]byte, len(data)+1) // append nul byte to the end + copy(src, data) + + ctx := decoder.TakeRuntimeContext() + ctx.Buf = src + ctx.Option.Flags = 0 + ctx.Option.Flags |= decoder.PathOption + ctx.Option.Path = path.path + for _, optFunc := range optFuncs { + optFunc(ctx.Option) + } + paths, cursor, err := pathDecoder.DecodePath(ctx, 0, 0) + if err != nil { + decoder.ReleaseRuntimeContext(ctx) + return nil, err + } + decoder.ReleaseRuntimeContext(ctx) + if err := validateEndBuf(src, cursor); err != nil { + return nil, err + } + return paths, nil +} + +func unmarshalNoEscape(data []byte, v interface{}, optFuncs ...DecodeOptionFunc) error { + src := make([]byte, len(data)+1) // append nul byte to the end + copy(src, data) + + header := (*emptyInterface)(unsafe.Pointer(&v)) + + if err := validateType(header.typ, uintptr(header.ptr)); err != nil { + return err + } + dec, err := decoder.CompileToGetDecoder(header.typ) + if err != nil { + return err + } + + ctx := decoder.TakeRuntimeContext() + ctx.Buf = src + ctx.Option.Flags = 0 + for _, optFunc := range optFuncs { + optFunc(ctx.Option) + } + cursor, err := dec.Decode(ctx, 0, 0, noescape(header.ptr)) + if err != nil { + decoder.ReleaseRuntimeContext(ctx) + return err + } + decoder.ReleaseRuntimeContext(ctx) + return validateEndBuf(src, cursor) +} + +func validateEndBuf(src []byte, cursor int64) error { + for { + switch src[cursor] { + case ' ', '\t', '\n', '\r': + cursor++ + continue + case nul: + return nil + } + return errors.ErrSyntax( + fmt.Sprintf("invalid character '%c' after top-level value", src[cursor]), + cursor+1, + ) + } +} + +//nolint:staticcheck +//go:nosplit +func noescape(p unsafe.Pointer) unsafe.Pointer { + x := uintptr(p) + return unsafe.Pointer(x ^ 0) +} + +func validateType(typ *runtime.Type, p uintptr) error { + if typ == nil || typ.Kind() != reflect.Ptr || p == 0 { + return &InvalidUnmarshalError{Type: runtime.RType2Type(typ)} + } + return nil +} + +// NewDecoder returns a new decoder that reads from r. +// +// The decoder introduces its own buffering and may +// read data from r beyond the JSON values requested. +func NewDecoder(r io.Reader) *Decoder { + s := decoder.NewStream(r) + return &Decoder{ + s: s, + } +} + +// Buffered returns a reader of the data remaining in the Decoder's +// buffer. The reader is valid until the next call to Decode. +func (d *Decoder) Buffered() io.Reader { + return d.s.Buffered() +} + +// Decode reads the next JSON-encoded value from its +// input and stores it in the value pointed to by v. +// +// See the documentation for Unmarshal for details about +// the conversion of JSON into a Go value. +func (d *Decoder) Decode(v interface{}) error { + return d.DecodeWithOption(v) +} + +// DecodeContext reads the next JSON-encoded value from its +// input and stores it in the value pointed to by v with context.Context. +func (d *Decoder) DecodeContext(ctx context.Context, v interface{}) error { + d.s.Option.Flags |= decoder.ContextOption + d.s.Option.Context = ctx + return d.DecodeWithOption(v) +} + +func (d *Decoder) DecodeWithOption(v interface{}, optFuncs ...DecodeOptionFunc) error { + header := (*emptyInterface)(unsafe.Pointer(&v)) + typ := header.typ + ptr := uintptr(header.ptr) + typeptr := uintptr(unsafe.Pointer(typ)) + // noescape trick for header.typ ( reflect.*rtype ) + copiedType := *(**runtime.Type)(unsafe.Pointer(&typeptr)) + + if err := validateType(copiedType, ptr); err != nil { + return err + } + + dec, err := decoder.CompileToGetDecoder(typ) + if err != nil { + return err + } + if err := d.s.PrepareForDecode(); err != nil { + return err + } + s := d.s + for _, optFunc := range optFuncs { + optFunc(s.Option) + } + if err := dec.DecodeStream(s, 0, header.ptr); err != nil { + return err + } + s.Reset() + return nil +} + +func (d *Decoder) More() bool { + return d.s.More() +} + +func (d *Decoder) Token() (Token, error) { + return d.s.Token() +} + +// DisallowUnknownFields causes the Decoder to return an error when the destination +// is a struct and the input contains object keys which do not match any +// non-ignored, exported fields in the destination. +func (d *Decoder) DisallowUnknownFields() { + d.s.DisallowUnknownFields = true +} + +func (d *Decoder) InputOffset() int64 { + return d.s.TotalOffset() +} + +// UseNumber causes the Decoder to unmarshal a number into an interface{} as a +// Number instead of as a float64. +func (d *Decoder) UseNumber() { + d.s.UseNumber = true +} diff --git a/vendor/github.com/goccy/go-json/docker-compose.yml b/vendor/github.com/goccy/go-json/docker-compose.yml new file mode 100644 index 000000000..db40c79ad --- /dev/null +++ b/vendor/github.com/goccy/go-json/docker-compose.yml @@ -0,0 +1,13 @@ +version: '2' +services: + go-json: + image: golang:1.18 + volumes: + - '.:/go/src/go-json' + deploy: + resources: + limits: + memory: 620M + working_dir: /go/src/go-json + command: | + sh -c "go test -c . && ls go-json.test" diff --git a/vendor/github.com/goccy/go-json/encode.go b/vendor/github.com/goccy/go-json/encode.go new file mode 100644 index 000000000..4bd899f38 --- /dev/null +++ b/vendor/github.com/goccy/go-json/encode.go @@ -0,0 +1,326 @@ +package json + +import ( + "context" + "io" + "os" + "unsafe" + + "github.com/goccy/go-json/internal/encoder" + "github.com/goccy/go-json/internal/encoder/vm" + "github.com/goccy/go-json/internal/encoder/vm_color" + "github.com/goccy/go-json/internal/encoder/vm_color_indent" + "github.com/goccy/go-json/internal/encoder/vm_indent" +) + +// An Encoder writes JSON values to an output stream. +type Encoder struct { + w io.Writer + enabledIndent bool + enabledHTMLEscape bool + prefix string + indentStr string +} + +// NewEncoder returns a new encoder that writes to w. +func NewEncoder(w io.Writer) *Encoder { + return &Encoder{w: w, enabledHTMLEscape: true} +} + +// Encode writes the JSON encoding of v to the stream, followed by a newline character. +// +// See the documentation for Marshal for details about the conversion of Go values to JSON. +func (e *Encoder) Encode(v interface{}) error { + return e.EncodeWithOption(v) +} + +// EncodeWithOption call Encode with EncodeOption. +func (e *Encoder) EncodeWithOption(v interface{}, optFuncs ...EncodeOptionFunc) error { + ctx := encoder.TakeRuntimeContext() + ctx.Option.Flag = 0 + + err := e.encodeWithOption(ctx, v, optFuncs...) + + encoder.ReleaseRuntimeContext(ctx) + return err +} + +// EncodeContext call Encode with context.Context and EncodeOption. +func (e *Encoder) EncodeContext(ctx context.Context, v interface{}, optFuncs ...EncodeOptionFunc) error { + rctx := encoder.TakeRuntimeContext() + rctx.Option.Flag = 0 + rctx.Option.Flag |= encoder.ContextOption + rctx.Option.Context = ctx + + err := e.encodeWithOption(rctx, v, optFuncs...) + + encoder.ReleaseRuntimeContext(rctx) + return err +} + +func (e *Encoder) encodeWithOption(ctx *encoder.RuntimeContext, v interface{}, optFuncs ...EncodeOptionFunc) error { + if e.enabledHTMLEscape { + ctx.Option.Flag |= encoder.HTMLEscapeOption + } + ctx.Option.Flag |= encoder.NormalizeUTF8Option + ctx.Option.DebugOut = os.Stdout + for _, optFunc := range optFuncs { + optFunc(ctx.Option) + } + var ( + buf []byte + err error + ) + if e.enabledIndent { + buf, err = encodeIndent(ctx, v, e.prefix, e.indentStr) + } else { + buf, err = encode(ctx, v) + } + if err != nil { + return err + } + if e.enabledIndent { + buf = buf[:len(buf)-2] + } else { + buf = buf[:len(buf)-1] + } + buf = append(buf, '\n') + if _, err := e.w.Write(buf); err != nil { + return err + } + return nil +} + +// SetEscapeHTML specifies whether problematic HTML characters should be escaped inside JSON quoted strings. +// The default behavior is to escape &, <, and > to \u0026, \u003c, and \u003e to avoid certain safety problems that can arise when embedding JSON in HTML. +// +// In non-HTML settings where the escaping interferes with the readability of the output, SetEscapeHTML(false) disables this behavior. +func (e *Encoder) SetEscapeHTML(on bool) { + e.enabledHTMLEscape = on +} + +// SetIndent instructs the encoder to format each subsequent encoded value as if indented by the package-level function Indent(dst, src, prefix, indent). +// Calling SetIndent("", "") disables indentation. +func (e *Encoder) SetIndent(prefix, indent string) { + if prefix == "" && indent == "" { + e.enabledIndent = false + return + } + e.prefix = prefix + e.indentStr = indent + e.enabledIndent = true +} + +func marshalContext(ctx context.Context, v interface{}, optFuncs ...EncodeOptionFunc) ([]byte, error) { + rctx := encoder.TakeRuntimeContext() + rctx.Option.Flag = 0 + rctx.Option.Flag = encoder.HTMLEscapeOption | encoder.NormalizeUTF8Option | encoder.ContextOption + rctx.Option.Context = ctx + for _, optFunc := range optFuncs { + optFunc(rctx.Option) + } + + buf, err := encode(rctx, v) + if err != nil { + encoder.ReleaseRuntimeContext(rctx) + return nil, err + } + + // this line exists to escape call of `runtime.makeslicecopy` . + // if use `make([]byte, len(buf)-1)` and `copy(copied, buf)`, + // dst buffer size and src buffer size are differrent. + // in this case, compiler uses `runtime.makeslicecopy`, but it is slow. + buf = buf[:len(buf)-1] + copied := make([]byte, len(buf)) + copy(copied, buf) + + encoder.ReleaseRuntimeContext(rctx) + return copied, nil +} + +func marshal(v interface{}, optFuncs ...EncodeOptionFunc) ([]byte, error) { + ctx := encoder.TakeRuntimeContext() + + ctx.Option.Flag = 0 + ctx.Option.Flag |= (encoder.HTMLEscapeOption | encoder.NormalizeUTF8Option) + for _, optFunc := range optFuncs { + optFunc(ctx.Option) + } + + buf, err := encode(ctx, v) + if err != nil { + encoder.ReleaseRuntimeContext(ctx) + return nil, err + } + + // this line exists to escape call of `runtime.makeslicecopy` . + // if use `make([]byte, len(buf)-1)` and `copy(copied, buf)`, + // dst buffer size and src buffer size are differrent. + // in this case, compiler uses `runtime.makeslicecopy`, but it is slow. + buf = buf[:len(buf)-1] + copied := make([]byte, len(buf)) + copy(copied, buf) + + encoder.ReleaseRuntimeContext(ctx) + return copied, nil +} + +func marshalNoEscape(v interface{}) ([]byte, error) { + ctx := encoder.TakeRuntimeContext() + + ctx.Option.Flag = 0 + ctx.Option.Flag |= (encoder.HTMLEscapeOption | encoder.NormalizeUTF8Option) + + buf, err := encodeNoEscape(ctx, v) + if err != nil { + encoder.ReleaseRuntimeContext(ctx) + return nil, err + } + + // this line exists to escape call of `runtime.makeslicecopy` . + // if use `make([]byte, len(buf)-1)` and `copy(copied, buf)`, + // dst buffer size and src buffer size are differrent. + // in this case, compiler uses `runtime.makeslicecopy`, but it is slow. + buf = buf[:len(buf)-1] + copied := make([]byte, len(buf)) + copy(copied, buf) + + encoder.ReleaseRuntimeContext(ctx) + return copied, nil +} + +func marshalIndent(v interface{}, prefix, indent string, optFuncs ...EncodeOptionFunc) ([]byte, error) { + ctx := encoder.TakeRuntimeContext() + + ctx.Option.Flag = 0 + ctx.Option.Flag |= (encoder.HTMLEscapeOption | encoder.NormalizeUTF8Option | encoder.IndentOption) + for _, optFunc := range optFuncs { + optFunc(ctx.Option) + } + + buf, err := encodeIndent(ctx, v, prefix, indent) + if err != nil { + encoder.ReleaseRuntimeContext(ctx) + return nil, err + } + + buf = buf[:len(buf)-2] + copied := make([]byte, len(buf)) + copy(copied, buf) + + encoder.ReleaseRuntimeContext(ctx) + return copied, nil +} + +func encode(ctx *encoder.RuntimeContext, v interface{}) ([]byte, error) { + b := ctx.Buf[:0] + if v == nil { + b = encoder.AppendNull(ctx, b) + b = encoder.AppendComma(ctx, b) + return b, nil + } + header := (*emptyInterface)(unsafe.Pointer(&v)) + typ := header.typ + + typeptr := uintptr(unsafe.Pointer(typ)) + codeSet, err := encoder.CompileToGetCodeSet(ctx, typeptr) + if err != nil { + return nil, err + } + + p := uintptr(header.ptr) + ctx.Init(p, codeSet.CodeLength) + ctx.KeepRefs = append(ctx.KeepRefs, header.ptr) + + buf, err := encodeRunCode(ctx, b, codeSet) + if err != nil { + return nil, err + } + ctx.Buf = buf + return buf, nil +} + +func encodeNoEscape(ctx *encoder.RuntimeContext, v interface{}) ([]byte, error) { + b := ctx.Buf[:0] + if v == nil { + b = encoder.AppendNull(ctx, b) + b = encoder.AppendComma(ctx, b) + return b, nil + } + header := (*emptyInterface)(unsafe.Pointer(&v)) + typ := header.typ + + typeptr := uintptr(unsafe.Pointer(typ)) + codeSet, err := encoder.CompileToGetCodeSet(ctx, typeptr) + if err != nil { + return nil, err + } + + p := uintptr(header.ptr) + ctx.Init(p, codeSet.CodeLength) + buf, err := encodeRunCode(ctx, b, codeSet) + if err != nil { + return nil, err + } + + ctx.Buf = buf + return buf, nil +} + +func encodeIndent(ctx *encoder.RuntimeContext, v interface{}, prefix, indent string) ([]byte, error) { + b := ctx.Buf[:0] + if v == nil { + b = encoder.AppendNull(ctx, b) + b = encoder.AppendCommaIndent(ctx, b) + return b, nil + } + header := (*emptyInterface)(unsafe.Pointer(&v)) + typ := header.typ + + typeptr := uintptr(unsafe.Pointer(typ)) + codeSet, err := encoder.CompileToGetCodeSet(ctx, typeptr) + if err != nil { + return nil, err + } + + p := uintptr(header.ptr) + ctx.Init(p, codeSet.CodeLength) + buf, err := encodeRunIndentCode(ctx, b, codeSet, prefix, indent) + + ctx.KeepRefs = append(ctx.KeepRefs, header.ptr) + + if err != nil { + return nil, err + } + + ctx.Buf = buf + return buf, nil +} + +func encodeRunCode(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) { + if (ctx.Option.Flag & encoder.DebugOption) != 0 { + if (ctx.Option.Flag & encoder.ColorizeOption) != 0 { + return vm_color.DebugRun(ctx, b, codeSet) + } + return vm.DebugRun(ctx, b, codeSet) + } + if (ctx.Option.Flag & encoder.ColorizeOption) != 0 { + return vm_color.Run(ctx, b, codeSet) + } + return vm.Run(ctx, b, codeSet) +} + +func encodeRunIndentCode(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, prefix, indent string) ([]byte, error) { + ctx.Prefix = []byte(prefix) + ctx.IndentStr = []byte(indent) + if (ctx.Option.Flag & encoder.DebugOption) != 0 { + if (ctx.Option.Flag & encoder.ColorizeOption) != 0 { + return vm_color_indent.DebugRun(ctx, b, codeSet) + } + return vm_indent.DebugRun(ctx, b, codeSet) + } + if (ctx.Option.Flag & encoder.ColorizeOption) != 0 { + return vm_color_indent.Run(ctx, b, codeSet) + } + return vm_indent.Run(ctx, b, codeSet) +} diff --git a/vendor/github.com/goccy/go-json/error.go b/vendor/github.com/goccy/go-json/error.go new file mode 100644 index 000000000..5b2dcee50 --- /dev/null +++ b/vendor/github.com/goccy/go-json/error.go @@ -0,0 +1,41 @@ +package json + +import ( + "github.com/goccy/go-json/internal/errors" +) + +// Before Go 1.2, an InvalidUTF8Error was returned by Marshal when +// attempting to encode a string value with invalid UTF-8 sequences. +// As of Go 1.2, Marshal instead coerces the string to valid UTF-8 by +// replacing invalid bytes with the Unicode replacement rune U+FFFD. +// +// Deprecated: No longer used; kept for compatibility. +type InvalidUTF8Error = errors.InvalidUTF8Error + +// An InvalidUnmarshalError describes an invalid argument passed to Unmarshal. +// (The argument to Unmarshal must be a non-nil pointer.) +type InvalidUnmarshalError = errors.InvalidUnmarshalError + +// A MarshalerError represents an error from calling a MarshalJSON or MarshalText method. +type MarshalerError = errors.MarshalerError + +// A SyntaxError is a description of a JSON syntax error. +type SyntaxError = errors.SyntaxError + +// An UnmarshalFieldError describes a JSON object key that +// led to an unexported (and therefore unwritable) struct field. +// +// Deprecated: No longer used; kept for compatibility. +type UnmarshalFieldError = errors.UnmarshalFieldError + +// An UnmarshalTypeError describes a JSON value that was +// not appropriate for a value of a specific Go type. +type UnmarshalTypeError = errors.UnmarshalTypeError + +// An UnsupportedTypeError is returned by Marshal when attempting +// to encode an unsupported value type. +type UnsupportedTypeError = errors.UnsupportedTypeError + +type UnsupportedValueError = errors.UnsupportedValueError + +type PathError = errors.PathError diff --git a/vendor/github.com/goccy/go-json/internal/decoder/anonymous_field.go b/vendor/github.com/goccy/go-json/internal/decoder/anonymous_field.go new file mode 100644 index 000000000..b6876cf0d --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/decoder/anonymous_field.go @@ -0,0 +1,41 @@ +package decoder + +import ( + "unsafe" + + "github.com/goccy/go-json/internal/runtime" +) + +type anonymousFieldDecoder struct { + structType *runtime.Type + offset uintptr + dec Decoder +} + +func newAnonymousFieldDecoder(structType *runtime.Type, offset uintptr, dec Decoder) *anonymousFieldDecoder { + return &anonymousFieldDecoder{ + structType: structType, + offset: offset, + dec: dec, + } +} + +func (d *anonymousFieldDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error { + if *(*unsafe.Pointer)(p) == nil { + *(*unsafe.Pointer)(p) = unsafe_New(d.structType) + } + p = *(*unsafe.Pointer)(p) + return d.dec.DecodeStream(s, depth, unsafe.Pointer(uintptr(p)+d.offset)) +} + +func (d *anonymousFieldDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { + if *(*unsafe.Pointer)(p) == nil { + *(*unsafe.Pointer)(p) = unsafe_New(d.structType) + } + p = *(*unsafe.Pointer)(p) + return d.dec.Decode(ctx, cursor, depth, unsafe.Pointer(uintptr(p)+d.offset)) +} + +func (d *anonymousFieldDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) { + return d.dec.DecodePath(ctx, cursor, depth) +} diff --git a/vendor/github.com/goccy/go-json/internal/decoder/array.go b/vendor/github.com/goccy/go-json/internal/decoder/array.go new file mode 100644 index 000000000..4b23ed43f --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/decoder/array.go @@ -0,0 +1,176 @@ +package decoder + +import ( + "fmt" + "unsafe" + + "github.com/goccy/go-json/internal/errors" + "github.com/goccy/go-json/internal/runtime" +) + +type arrayDecoder struct { + elemType *runtime.Type + size uintptr + valueDecoder Decoder + alen int + structName string + fieldName string + zeroValue unsafe.Pointer +} + +func newArrayDecoder(dec Decoder, elemType *runtime.Type, alen int, structName, fieldName string) *arrayDecoder { + // workaround to avoid checkptr errors. cannot use `*(*unsafe.Pointer)(unsafe_New(elemType))` directly. + zeroValuePtr := unsafe_New(elemType) + zeroValue := **(**unsafe.Pointer)(unsafe.Pointer(&zeroValuePtr)) + return &arrayDecoder{ + valueDecoder: dec, + elemType: elemType, + size: elemType.Size(), + alen: alen, + structName: structName, + fieldName: fieldName, + zeroValue: zeroValue, + } +} + +func (d *arrayDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error { + depth++ + if depth > maxDecodeNestingDepth { + return errors.ErrExceededMaxDepth(s.char(), s.cursor) + } + + for { + switch s.char() { + case ' ', '\n', '\t', '\r': + case 'n': + if err := nullBytes(s); err != nil { + return err + } + return nil + case '[': + idx := 0 + s.cursor++ + if s.skipWhiteSpace() == ']' { + for idx < d.alen { + *(*unsafe.Pointer)(unsafe.Pointer(uintptr(p) + uintptr(idx)*d.size)) = d.zeroValue + idx++ + } + s.cursor++ + return nil + } + for { + if idx < d.alen { + if err := d.valueDecoder.DecodeStream(s, depth, unsafe.Pointer(uintptr(p)+uintptr(idx)*d.size)); err != nil { + return err + } + } else { + if err := s.skipValue(depth); err != nil { + return err + } + } + idx++ + switch s.skipWhiteSpace() { + case ']': + for idx < d.alen { + *(*unsafe.Pointer)(unsafe.Pointer(uintptr(p) + uintptr(idx)*d.size)) = d.zeroValue + idx++ + } + s.cursor++ + return nil + case ',': + s.cursor++ + continue + case nul: + if s.read() { + s.cursor++ + continue + } + goto ERROR + default: + goto ERROR + } + } + case nul: + if s.read() { + continue + } + goto ERROR + default: + goto ERROR + } + s.cursor++ + } +ERROR: + return errors.ErrUnexpectedEndOfJSON("array", s.totalOffset()) +} + +func (d *arrayDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { + buf := ctx.Buf + depth++ + if depth > maxDecodeNestingDepth { + return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor) + } + + for { + switch buf[cursor] { + case ' ', '\n', '\t', '\r': + cursor++ + continue + case 'n': + if err := validateNull(buf, cursor); err != nil { + return 0, err + } + cursor += 4 + return cursor, nil + case '[': + idx := 0 + cursor++ + cursor = skipWhiteSpace(buf, cursor) + if buf[cursor] == ']' { + for idx < d.alen { + *(*unsafe.Pointer)(unsafe.Pointer(uintptr(p) + uintptr(idx)*d.size)) = d.zeroValue + idx++ + } + cursor++ + return cursor, nil + } + for { + if idx < d.alen { + c, err := d.valueDecoder.Decode(ctx, cursor, depth, unsafe.Pointer(uintptr(p)+uintptr(idx)*d.size)) + if err != nil { + return 0, err + } + cursor = c + } else { + c, err := skipValue(buf, cursor, depth) + if err != nil { + return 0, err + } + cursor = c + } + idx++ + cursor = skipWhiteSpace(buf, cursor) + switch buf[cursor] { + case ']': + for idx < d.alen { + *(*unsafe.Pointer)(unsafe.Pointer(uintptr(p) + uintptr(idx)*d.size)) = d.zeroValue + idx++ + } + cursor++ + return cursor, nil + case ',': + cursor++ + continue + default: + return 0, errors.ErrInvalidCharacter(buf[cursor], "array", cursor) + } + } + default: + return 0, errors.ErrUnexpectedEndOfJSON("array", cursor) + } + } +} + +func (d *arrayDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) { + return nil, 0, fmt.Errorf("json: array decoder does not support decode path") +} diff --git a/vendor/github.com/goccy/go-json/internal/decoder/assign.go b/vendor/github.com/goccy/go-json/internal/decoder/assign.go new file mode 100644 index 000000000..c53e6ad9f --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/decoder/assign.go @@ -0,0 +1,438 @@ +package decoder + +import ( + "fmt" + "reflect" + "strconv" +) + +var ( + nilValue = reflect.ValueOf(nil) +) + +func AssignValue(src, dst reflect.Value) error { + if dst.Type().Kind() != reflect.Ptr { + return fmt.Errorf("invalid dst type. required pointer type: %T", dst.Type()) + } + casted, err := castValue(dst.Elem().Type(), src) + if err != nil { + return err + } + dst.Elem().Set(casted) + return nil +} + +func castValue(t reflect.Type, v reflect.Value) (reflect.Value, error) { + switch t.Kind() { + case reflect.Int: + vv, err := castInt(v) + if err != nil { + return nilValue, err + } + return reflect.ValueOf(int(vv.Int())), nil + case reflect.Int8: + vv, err := castInt(v) + if err != nil { + return nilValue, err + } + return reflect.ValueOf(int8(vv.Int())), nil + case reflect.Int16: + vv, err := castInt(v) + if err != nil { + return nilValue, err + } + return reflect.ValueOf(int16(vv.Int())), nil + case reflect.Int32: + vv, err := castInt(v) + if err != nil { + return nilValue, err + } + return reflect.ValueOf(int32(vv.Int())), nil + case reflect.Int64: + return castInt(v) + case reflect.Uint: + vv, err := castUint(v) + if err != nil { + return nilValue, err + } + return reflect.ValueOf(uint(vv.Uint())), nil + case reflect.Uint8: + vv, err := castUint(v) + if err != nil { + return nilValue, err + } + return reflect.ValueOf(uint8(vv.Uint())), nil + case reflect.Uint16: + vv, err := castUint(v) + if err != nil { + return nilValue, err + } + return reflect.ValueOf(uint16(vv.Uint())), nil + case reflect.Uint32: + vv, err := castUint(v) + if err != nil { + return nilValue, err + } + return reflect.ValueOf(uint32(vv.Uint())), nil + case reflect.Uint64: + return castUint(v) + case reflect.Uintptr: + vv, err := castUint(v) + if err != nil { + return nilValue, err + } + return reflect.ValueOf(uintptr(vv.Uint())), nil + case reflect.String: + return castString(v) + case reflect.Bool: + return castBool(v) + case reflect.Float32: + vv, err := castFloat(v) + if err != nil { + return nilValue, err + } + return reflect.ValueOf(float32(vv.Float())), nil + case reflect.Float64: + return castFloat(v) + case reflect.Array: + return castArray(t, v) + case reflect.Slice: + return castSlice(t, v) + case reflect.Map: + return castMap(t, v) + case reflect.Struct: + return castStruct(t, v) + } + return v, nil +} + +func castInt(v reflect.Value) (reflect.Value, error) { + switch v.Type().Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return v, nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return reflect.ValueOf(int64(v.Uint())), nil + case reflect.String: + i64, err := strconv.ParseInt(v.String(), 10, 64) + if err != nil { + return nilValue, err + } + return reflect.ValueOf(i64), nil + case reflect.Bool: + if v.Bool() { + return reflect.ValueOf(int64(1)), nil + } + return reflect.ValueOf(int64(0)), nil + case reflect.Float32, reflect.Float64: + return reflect.ValueOf(int64(v.Float())), nil + case reflect.Array: + if v.Len() > 0 { + return castInt(v.Index(0)) + } + return nilValue, fmt.Errorf("failed to cast to int64 from empty array") + case reflect.Slice: + if v.Len() > 0 { + return castInt(v.Index(0)) + } + return nilValue, fmt.Errorf("failed to cast to int64 from empty slice") + case reflect.Interface: + return castInt(reflect.ValueOf(v.Interface())) + case reflect.Map: + return nilValue, fmt.Errorf("failed to cast to int64 from map") + case reflect.Struct: + return nilValue, fmt.Errorf("failed to cast to int64 from struct") + case reflect.Ptr: + return castInt(v.Elem()) + } + return nilValue, fmt.Errorf("failed to cast to int64 from %s", v.Type().Kind()) +} + +func castUint(v reflect.Value) (reflect.Value, error) { + switch v.Type().Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return reflect.ValueOf(uint64(v.Int())), nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return v, nil + case reflect.String: + u64, err := strconv.ParseUint(v.String(), 10, 64) + if err != nil { + return nilValue, err + } + return reflect.ValueOf(u64), nil + case reflect.Bool: + if v.Bool() { + return reflect.ValueOf(uint64(1)), nil + } + return reflect.ValueOf(uint64(0)), nil + case reflect.Float32, reflect.Float64: + return reflect.ValueOf(uint64(v.Float())), nil + case reflect.Array: + if v.Len() > 0 { + return castUint(v.Index(0)) + } + return nilValue, fmt.Errorf("failed to cast to uint64 from empty array") + case reflect.Slice: + if v.Len() > 0 { + return castUint(v.Index(0)) + } + return nilValue, fmt.Errorf("failed to cast to uint64 from empty slice") + case reflect.Interface: + return castUint(reflect.ValueOf(v.Interface())) + case reflect.Map: + return nilValue, fmt.Errorf("failed to cast to uint64 from map") + case reflect.Struct: + return nilValue, fmt.Errorf("failed to cast to uint64 from struct") + case reflect.Ptr: + return castUint(v.Elem()) + } + return nilValue, fmt.Errorf("failed to cast to uint64 from %s", v.Type().Kind()) +} + +func castString(v reflect.Value) (reflect.Value, error) { + switch v.Type().Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return reflect.ValueOf(fmt.Sprint(v.Int())), nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return reflect.ValueOf(fmt.Sprint(v.Uint())), nil + case reflect.String: + return v, nil + case reflect.Bool: + if v.Bool() { + return reflect.ValueOf("true"), nil + } + return reflect.ValueOf("false"), nil + case reflect.Float32, reflect.Float64: + return reflect.ValueOf(fmt.Sprint(v.Float())), nil + case reflect.Array: + if v.Len() > 0 { + return castString(v.Index(0)) + } + return nilValue, fmt.Errorf("failed to cast to string from empty array") + case reflect.Slice: + if v.Len() > 0 { + return castString(v.Index(0)) + } + return nilValue, fmt.Errorf("failed to cast to string from empty slice") + case reflect.Interface: + return castString(reflect.ValueOf(v.Interface())) + case reflect.Map: + return nilValue, fmt.Errorf("failed to cast to string from map") + case reflect.Struct: + return nilValue, fmt.Errorf("failed to cast to string from struct") + case reflect.Ptr: + return castString(v.Elem()) + } + return nilValue, fmt.Errorf("failed to cast to string from %s", v.Type().Kind()) +} + +func castBool(v reflect.Value) (reflect.Value, error) { + switch v.Type().Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + switch v.Int() { + case 0: + return reflect.ValueOf(false), nil + case 1: + return reflect.ValueOf(true), nil + } + return nilValue, fmt.Errorf("failed to cast to bool from %d", v.Int()) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + switch v.Uint() { + case 0: + return reflect.ValueOf(false), nil + case 1: + return reflect.ValueOf(true), nil + } + return nilValue, fmt.Errorf("failed to cast to bool from %d", v.Uint()) + case reflect.String: + b, err := strconv.ParseBool(v.String()) + if err != nil { + return nilValue, err + } + return reflect.ValueOf(b), nil + case reflect.Bool: + return v, nil + case reflect.Float32, reflect.Float64: + switch v.Float() { + case 0: + return reflect.ValueOf(false), nil + case 1: + return reflect.ValueOf(true), nil + } + return nilValue, fmt.Errorf("failed to cast to bool from %f", v.Float()) + case reflect.Array: + if v.Len() > 0 { + return castBool(v.Index(0)) + } + return nilValue, fmt.Errorf("failed to cast to string from empty array") + case reflect.Slice: + if v.Len() > 0 { + return castBool(v.Index(0)) + } + return nilValue, fmt.Errorf("failed to cast to string from empty slice") + case reflect.Interface: + return castBool(reflect.ValueOf(v.Interface())) + case reflect.Map: + return nilValue, fmt.Errorf("failed to cast to string from map") + case reflect.Struct: + return nilValue, fmt.Errorf("failed to cast to string from struct") + case reflect.Ptr: + return castBool(v.Elem()) + } + return nilValue, fmt.Errorf("failed to cast to bool from %s", v.Type().Kind()) +} + +func castFloat(v reflect.Value) (reflect.Value, error) { + switch v.Type().Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return reflect.ValueOf(float64(v.Int())), nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return reflect.ValueOf(float64(v.Uint())), nil + case reflect.String: + f64, err := strconv.ParseFloat(v.String(), 64) + if err != nil { + return nilValue, err + } + return reflect.ValueOf(f64), nil + case reflect.Bool: + if v.Bool() { + return reflect.ValueOf(float64(1)), nil + } + return reflect.ValueOf(float64(0)), nil + case reflect.Float32, reflect.Float64: + return v, nil + case reflect.Array: + if v.Len() > 0 { + return castFloat(v.Index(0)) + } + return nilValue, fmt.Errorf("failed to cast to float64 from empty array") + case reflect.Slice: + if v.Len() > 0 { + return castFloat(v.Index(0)) + } + return nilValue, fmt.Errorf("failed to cast to float64 from empty slice") + case reflect.Interface: + return castFloat(reflect.ValueOf(v.Interface())) + case reflect.Map: + return nilValue, fmt.Errorf("failed to cast to float64 from map") + case reflect.Struct: + return nilValue, fmt.Errorf("failed to cast to float64 from struct") + case reflect.Ptr: + return castFloat(v.Elem()) + } + return nilValue, fmt.Errorf("failed to cast to float64 from %s", v.Type().Kind()) +} + +func castArray(t reflect.Type, v reflect.Value) (reflect.Value, error) { + kind := v.Type().Kind() + if kind == reflect.Interface { + return castArray(t, reflect.ValueOf(v.Interface())) + } + if kind != reflect.Slice && kind != reflect.Array { + return nilValue, fmt.Errorf("failed to cast to array from %s", kind) + } + if t.Elem() == v.Type().Elem() { + return v, nil + } + if t.Len() != v.Len() { + return nilValue, fmt.Errorf("failed to cast [%d]array from slice of %d length", t.Len(), v.Len()) + } + ret := reflect.New(t).Elem() + for i := 0; i < v.Len(); i++ { + vv, err := castValue(t.Elem(), v.Index(i)) + if err != nil { + return nilValue, err + } + ret.Index(i).Set(vv) + } + return ret, nil +} + +func castSlice(t reflect.Type, v reflect.Value) (reflect.Value, error) { + kind := v.Type().Kind() + if kind == reflect.Interface { + return castSlice(t, reflect.ValueOf(v.Interface())) + } + if kind != reflect.Slice && kind != reflect.Array { + return nilValue, fmt.Errorf("failed to cast to slice from %s", kind) + } + if t.Elem() == v.Type().Elem() { + return v, nil + } + ret := reflect.MakeSlice(t, v.Len(), v.Len()) + for i := 0; i < v.Len(); i++ { + vv, err := castValue(t.Elem(), v.Index(i)) + if err != nil { + return nilValue, err + } + ret.Index(i).Set(vv) + } + return ret, nil +} + +func castMap(t reflect.Type, v reflect.Value) (reflect.Value, error) { + ret := reflect.MakeMap(t) + switch v.Type().Kind() { + case reflect.Map: + iter := v.MapRange() + for iter.Next() { + key, err := castValue(t.Key(), iter.Key()) + if err != nil { + return nilValue, err + } + value, err := castValue(t.Elem(), iter.Value()) + if err != nil { + return nilValue, err + } + ret.SetMapIndex(key, value) + } + return ret, nil + case reflect.Interface: + return castMap(t, reflect.ValueOf(v.Interface())) + case reflect.Slice: + if v.Len() > 0 { + return castMap(t, v.Index(0)) + } + return nilValue, fmt.Errorf("failed to cast to map from empty slice") + } + return nilValue, fmt.Errorf("failed to cast to map from %s", v.Type().Kind()) +} + +func castStruct(t reflect.Type, v reflect.Value) (reflect.Value, error) { + ret := reflect.New(t).Elem() + switch v.Type().Kind() { + case reflect.Map: + iter := v.MapRange() + for iter.Next() { + key := iter.Key() + k, err := castString(key) + if err != nil { + return nilValue, err + } + fieldName := k.String() + field, ok := t.FieldByName(fieldName) + if ok { + value, err := castValue(field.Type, iter.Value()) + if err != nil { + return nilValue, err + } + ret.FieldByName(fieldName).Set(value) + } + } + return ret, nil + case reflect.Struct: + for i := 0; i < v.Type().NumField(); i++ { + name := v.Type().Field(i).Name + ret.FieldByName(name).Set(v.FieldByName(name)) + } + return ret, nil + case reflect.Interface: + return castStruct(t, reflect.ValueOf(v.Interface())) + case reflect.Slice: + if v.Len() > 0 { + return castStruct(t, v.Index(0)) + } + return nilValue, fmt.Errorf("failed to cast to struct from empty slice") + default: + return nilValue, fmt.Errorf("failed to cast to struct from %s", v.Type().Kind()) + } +} diff --git a/vendor/github.com/goccy/go-json/internal/decoder/bool.go b/vendor/github.com/goccy/go-json/internal/decoder/bool.go new file mode 100644 index 000000000..ba6cf5bc4 --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/decoder/bool.go @@ -0,0 +1,83 @@ +package decoder + +import ( + "fmt" + "unsafe" + + "github.com/goccy/go-json/internal/errors" +) + +type boolDecoder struct { + structName string + fieldName string +} + +func newBoolDecoder(structName, fieldName string) *boolDecoder { + return &boolDecoder{structName: structName, fieldName: fieldName} +} + +func (d *boolDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error { + c := s.skipWhiteSpace() + for { + switch c { + case 't': + if err := trueBytes(s); err != nil { + return err + } + **(**bool)(unsafe.Pointer(&p)) = true + return nil + case 'f': + if err := falseBytes(s); err != nil { + return err + } + **(**bool)(unsafe.Pointer(&p)) = false + return nil + case 'n': + if err := nullBytes(s); err != nil { + return err + } + return nil + case nul: + if s.read() { + c = s.char() + continue + } + goto ERROR + } + break + } +ERROR: + return errors.ErrUnexpectedEndOfJSON("bool", s.totalOffset()) +} + +func (d *boolDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { + buf := ctx.Buf + cursor = skipWhiteSpace(buf, cursor) + switch buf[cursor] { + case 't': + if err := validateTrue(buf, cursor); err != nil { + return 0, err + } + cursor += 4 + **(**bool)(unsafe.Pointer(&p)) = true + return cursor, nil + case 'f': + if err := validateFalse(buf, cursor); err != nil { + return 0, err + } + cursor += 5 + **(**bool)(unsafe.Pointer(&p)) = false + return cursor, nil + case 'n': + if err := validateNull(buf, cursor); err != nil { + return 0, err + } + cursor += 4 + return cursor, nil + } + return 0, errors.ErrUnexpectedEndOfJSON("bool", cursor) +} + +func (d *boolDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) { + return nil, 0, fmt.Errorf("json: bool decoder does not support decode path") +} diff --git a/vendor/github.com/goccy/go-json/internal/decoder/bytes.go b/vendor/github.com/goccy/go-json/internal/decoder/bytes.go new file mode 100644 index 000000000..939bf4327 --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/decoder/bytes.go @@ -0,0 +1,118 @@ +package decoder + +import ( + "encoding/base64" + "fmt" + "unsafe" + + "github.com/goccy/go-json/internal/errors" + "github.com/goccy/go-json/internal/runtime" +) + +type bytesDecoder struct { + typ *runtime.Type + sliceDecoder Decoder + stringDecoder *stringDecoder + structName string + fieldName string +} + +func byteUnmarshalerSliceDecoder(typ *runtime.Type, structName string, fieldName string) Decoder { + var unmarshalDecoder Decoder + switch { + case runtime.PtrTo(typ).Implements(unmarshalJSONType): + unmarshalDecoder = newUnmarshalJSONDecoder(runtime.PtrTo(typ), structName, fieldName) + case runtime.PtrTo(typ).Implements(unmarshalTextType): + unmarshalDecoder = newUnmarshalTextDecoder(runtime.PtrTo(typ), structName, fieldName) + default: + unmarshalDecoder, _ = compileUint8(typ, structName, fieldName) + } + return newSliceDecoder(unmarshalDecoder, typ, 1, structName, fieldName) +} + +func newBytesDecoder(typ *runtime.Type, structName string, fieldName string) *bytesDecoder { + return &bytesDecoder{ + typ: typ, + sliceDecoder: byteUnmarshalerSliceDecoder(typ, structName, fieldName), + stringDecoder: newStringDecoder(structName, fieldName), + structName: structName, + fieldName: fieldName, + } +} + +func (d *bytesDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error { + bytes, err := d.decodeStreamBinary(s, depth, p) + if err != nil { + return err + } + if bytes == nil { + s.reset() + return nil + } + decodedLen := base64.StdEncoding.DecodedLen(len(bytes)) + buf := make([]byte, decodedLen) + n, err := base64.StdEncoding.Decode(buf, bytes) + if err != nil { + return err + } + *(*[]byte)(p) = buf[:n] + s.reset() + return nil +} + +func (d *bytesDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { + bytes, c, err := d.decodeBinary(ctx, cursor, depth, p) + if err != nil { + return 0, err + } + if bytes == nil { + return c, nil + } + cursor = c + decodedLen := base64.StdEncoding.DecodedLen(len(bytes)) + b := make([]byte, decodedLen) + n, err := base64.StdEncoding.Decode(b, bytes) + if err != nil { + return 0, err + } + *(*[]byte)(p) = b[:n] + return cursor, nil +} + +func (d *bytesDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) { + return nil, 0, fmt.Errorf("json: []byte decoder does not support decode path") +} + +func (d *bytesDecoder) decodeStreamBinary(s *Stream, depth int64, p unsafe.Pointer) ([]byte, error) { + c := s.skipWhiteSpace() + if c == '[' { + if d.sliceDecoder == nil { + return nil, &errors.UnmarshalTypeError{ + Type: runtime.RType2Type(d.typ), + Offset: s.totalOffset(), + } + } + err := d.sliceDecoder.DecodeStream(s, depth, p) + return nil, err + } + return d.stringDecoder.decodeStreamByte(s) +} + +func (d *bytesDecoder) decodeBinary(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) ([]byte, int64, error) { + buf := ctx.Buf + cursor = skipWhiteSpace(buf, cursor) + if buf[cursor] == '[' { + if d.sliceDecoder == nil { + return nil, 0, &errors.UnmarshalTypeError{ + Type: runtime.RType2Type(d.typ), + Offset: cursor, + } + } + c, err := d.sliceDecoder.Decode(ctx, cursor, depth, p) + if err != nil { + return nil, 0, err + } + return nil, c, nil + } + return d.stringDecoder.decodeByte(buf, cursor) +} diff --git a/vendor/github.com/goccy/go-json/internal/decoder/compile.go b/vendor/github.com/goccy/go-json/internal/decoder/compile.go new file mode 100644 index 000000000..fab643764 --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/decoder/compile.go @@ -0,0 +1,487 @@ +package decoder + +import ( + "encoding/json" + "fmt" + "reflect" + "strings" + "sync/atomic" + "unicode" + "unsafe" + + "github.com/goccy/go-json/internal/runtime" +) + +var ( + jsonNumberType = reflect.TypeOf(json.Number("")) + typeAddr *runtime.TypeAddr + cachedDecoderMap unsafe.Pointer // map[uintptr]decoder + cachedDecoder []Decoder +) + +func init() { + typeAddr = runtime.AnalyzeTypeAddr() + if typeAddr == nil { + typeAddr = &runtime.TypeAddr{} + } + cachedDecoder = make([]Decoder, typeAddr.AddrRange>>typeAddr.AddrShift+1) +} + +func loadDecoderMap() map[uintptr]Decoder { + p := atomic.LoadPointer(&cachedDecoderMap) + return *(*map[uintptr]Decoder)(unsafe.Pointer(&p)) +} + +func storeDecoder(typ uintptr, dec Decoder, m map[uintptr]Decoder) { + newDecoderMap := make(map[uintptr]Decoder, len(m)+1) + newDecoderMap[typ] = dec + + for k, v := range m { + newDecoderMap[k] = v + } + + atomic.StorePointer(&cachedDecoderMap, *(*unsafe.Pointer)(unsafe.Pointer(&newDecoderMap))) +} + +func compileToGetDecoderSlowPath(typeptr uintptr, typ *runtime.Type) (Decoder, error) { + decoderMap := loadDecoderMap() + if dec, exists := decoderMap[typeptr]; exists { + return dec, nil + } + + dec, err := compileHead(typ, map[uintptr]Decoder{}) + if err != nil { + return nil, err + } + storeDecoder(typeptr, dec, decoderMap) + return dec, nil +} + +func compileHead(typ *runtime.Type, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) { + switch { + case implementsUnmarshalJSONType(runtime.PtrTo(typ)): + return newUnmarshalJSONDecoder(runtime.PtrTo(typ), "", ""), nil + case runtime.PtrTo(typ).Implements(unmarshalTextType): + return newUnmarshalTextDecoder(runtime.PtrTo(typ), "", ""), nil + } + return compile(typ.Elem(), "", "", structTypeToDecoder) +} + +func compile(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) { + switch { + case implementsUnmarshalJSONType(runtime.PtrTo(typ)): + return newUnmarshalJSONDecoder(runtime.PtrTo(typ), structName, fieldName), nil + case runtime.PtrTo(typ).Implements(unmarshalTextType): + return newUnmarshalTextDecoder(runtime.PtrTo(typ), structName, fieldName), nil + } + + switch typ.Kind() { + case reflect.Ptr: + return compilePtr(typ, structName, fieldName, structTypeToDecoder) + case reflect.Struct: + return compileStruct(typ, structName, fieldName, structTypeToDecoder) + case reflect.Slice: + elem := typ.Elem() + if elem.Kind() == reflect.Uint8 { + return compileBytes(elem, structName, fieldName) + } + return compileSlice(typ, structName, fieldName, structTypeToDecoder) + case reflect.Array: + return compileArray(typ, structName, fieldName, structTypeToDecoder) + case reflect.Map: + return compileMap(typ, structName, fieldName, structTypeToDecoder) + case reflect.Interface: + return compileInterface(typ, structName, fieldName) + case reflect.Uintptr: + return compileUint(typ, structName, fieldName) + case reflect.Int: + return compileInt(typ, structName, fieldName) + case reflect.Int8: + return compileInt8(typ, structName, fieldName) + case reflect.Int16: + return compileInt16(typ, structName, fieldName) + case reflect.Int32: + return compileInt32(typ, structName, fieldName) + case reflect.Int64: + return compileInt64(typ, structName, fieldName) + case reflect.Uint: + return compileUint(typ, structName, fieldName) + case reflect.Uint8: + return compileUint8(typ, structName, fieldName) + case reflect.Uint16: + return compileUint16(typ, structName, fieldName) + case reflect.Uint32: + return compileUint32(typ, structName, fieldName) + case reflect.Uint64: + return compileUint64(typ, structName, fieldName) + case reflect.String: + return compileString(typ, structName, fieldName) + case reflect.Bool: + return compileBool(structName, fieldName) + case reflect.Float32: + return compileFloat32(structName, fieldName) + case reflect.Float64: + return compileFloat64(structName, fieldName) + case reflect.Func: + return compileFunc(typ, structName, fieldName) + } + return newInvalidDecoder(typ, structName, fieldName), nil +} + +func isStringTagSupportedType(typ *runtime.Type) bool { + switch { + case implementsUnmarshalJSONType(runtime.PtrTo(typ)): + return false + case runtime.PtrTo(typ).Implements(unmarshalTextType): + return false + } + switch typ.Kind() { + case reflect.Map: + return false + case reflect.Slice: + return false + case reflect.Array: + return false + case reflect.Struct: + return false + case reflect.Interface: + return false + } + return true +} + +func compileMapKey(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) { + if runtime.PtrTo(typ).Implements(unmarshalTextType) { + return newUnmarshalTextDecoder(runtime.PtrTo(typ), structName, fieldName), nil + } + if typ.Kind() == reflect.String { + return newStringDecoder(structName, fieldName), nil + } + dec, err := compile(typ, structName, fieldName, structTypeToDecoder) + if err != nil { + return nil, err + } + for { + switch t := dec.(type) { + case *stringDecoder, *interfaceDecoder: + return dec, nil + case *boolDecoder, *intDecoder, *uintDecoder, *numberDecoder: + return newWrappedStringDecoder(typ, dec, structName, fieldName), nil + case *ptrDecoder: + dec = t.dec + default: + return newInvalidDecoder(typ, structName, fieldName), nil + } + } +} + +func compilePtr(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) { + dec, err := compile(typ.Elem(), structName, fieldName, structTypeToDecoder) + if err != nil { + return nil, err + } + return newPtrDecoder(dec, typ.Elem(), structName, fieldName), nil +} + +func compileInt(typ *runtime.Type, structName, fieldName string) (Decoder, error) { + return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) { + *(*int)(p) = int(v) + }), nil +} + +func compileInt8(typ *runtime.Type, structName, fieldName string) (Decoder, error) { + return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) { + *(*int8)(p) = int8(v) + }), nil +} + +func compileInt16(typ *runtime.Type, structName, fieldName string) (Decoder, error) { + return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) { + *(*int16)(p) = int16(v) + }), nil +} + +func compileInt32(typ *runtime.Type, structName, fieldName string) (Decoder, error) { + return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) { + *(*int32)(p) = int32(v) + }), nil +} + +func compileInt64(typ *runtime.Type, structName, fieldName string) (Decoder, error) { + return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) { + *(*int64)(p) = v + }), nil +} + +func compileUint(typ *runtime.Type, structName, fieldName string) (Decoder, error) { + return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) { + *(*uint)(p) = uint(v) + }), nil +} + +func compileUint8(typ *runtime.Type, structName, fieldName string) (Decoder, error) { + return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) { + *(*uint8)(p) = uint8(v) + }), nil +} + +func compileUint16(typ *runtime.Type, structName, fieldName string) (Decoder, error) { + return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) { + *(*uint16)(p) = uint16(v) + }), nil +} + +func compileUint32(typ *runtime.Type, structName, fieldName string) (Decoder, error) { + return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) { + *(*uint32)(p) = uint32(v) + }), nil +} + +func compileUint64(typ *runtime.Type, structName, fieldName string) (Decoder, error) { + return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) { + *(*uint64)(p) = v + }), nil +} + +func compileFloat32(structName, fieldName string) (Decoder, error) { + return newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) { + *(*float32)(p) = float32(v) + }), nil +} + +func compileFloat64(structName, fieldName string) (Decoder, error) { + return newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) { + *(*float64)(p) = v + }), nil +} + +func compileString(typ *runtime.Type, structName, fieldName string) (Decoder, error) { + if typ == runtime.Type2RType(jsonNumberType) { + return newNumberDecoder(structName, fieldName, func(p unsafe.Pointer, v json.Number) { + *(*json.Number)(p) = v + }), nil + } + return newStringDecoder(structName, fieldName), nil +} + +func compileBool(structName, fieldName string) (Decoder, error) { + return newBoolDecoder(structName, fieldName), nil +} + +func compileBytes(typ *runtime.Type, structName, fieldName string) (Decoder, error) { + return newBytesDecoder(typ, structName, fieldName), nil +} + +func compileSlice(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) { + elem := typ.Elem() + decoder, err := compile(elem, structName, fieldName, structTypeToDecoder) + if err != nil { + return nil, err + } + return newSliceDecoder(decoder, elem, elem.Size(), structName, fieldName), nil +} + +func compileArray(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) { + elem := typ.Elem() + decoder, err := compile(elem, structName, fieldName, structTypeToDecoder) + if err != nil { + return nil, err + } + return newArrayDecoder(decoder, elem, typ.Len(), structName, fieldName), nil +} + +func compileMap(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) { + keyDec, err := compileMapKey(typ.Key(), structName, fieldName, structTypeToDecoder) + if err != nil { + return nil, err + } + valueDec, err := compile(typ.Elem(), structName, fieldName, structTypeToDecoder) + if err != nil { + return nil, err + } + return newMapDecoder(typ, typ.Key(), keyDec, typ.Elem(), valueDec, structName, fieldName), nil +} + +func compileInterface(typ *runtime.Type, structName, fieldName string) (Decoder, error) { + return newInterfaceDecoder(typ, structName, fieldName), nil +} + +func compileFunc(typ *runtime.Type, strutName, fieldName string) (Decoder, error) { + return newFuncDecoder(typ, strutName, fieldName), nil +} + +func typeToStructTags(typ *runtime.Type) runtime.StructTags { + tags := runtime.StructTags{} + fieldNum := typ.NumField() + for i := 0; i < fieldNum; i++ { + field := typ.Field(i) + if runtime.IsIgnoredStructField(field) { + continue + } + tags = append(tags, runtime.StructTagFromField(field)) + } + return tags +} + +func compileStruct(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) { + fieldNum := typ.NumField() + fieldMap := map[string]*structFieldSet{} + typeptr := uintptr(unsafe.Pointer(typ)) + if dec, exists := structTypeToDecoder[typeptr]; exists { + return dec, nil + } + structDec := newStructDecoder(structName, fieldName, fieldMap) + structTypeToDecoder[typeptr] = structDec + structName = typ.Name() + tags := typeToStructTags(typ) + allFields := []*structFieldSet{} + for i := 0; i < fieldNum; i++ { + field := typ.Field(i) + if runtime.IsIgnoredStructField(field) { + continue + } + isUnexportedField := unicode.IsLower([]rune(field.Name)[0]) + tag := runtime.StructTagFromField(field) + dec, err := compile(runtime.Type2RType(field.Type), structName, field.Name, structTypeToDecoder) + if err != nil { + return nil, err + } + if field.Anonymous && !tag.IsTaggedKey { + if stDec, ok := dec.(*structDecoder); ok { + if runtime.Type2RType(field.Type) == typ { + // recursive definition + continue + } + for k, v := range stDec.fieldMap { + if tags.ExistsKey(k) { + continue + } + fieldSet := &structFieldSet{ + dec: v.dec, + offset: field.Offset + v.offset, + isTaggedKey: v.isTaggedKey, + key: k, + keyLen: int64(len(k)), + } + allFields = append(allFields, fieldSet) + } + } else if pdec, ok := dec.(*ptrDecoder); ok { + contentDec := pdec.contentDecoder() + if pdec.typ == typ { + // recursive definition + continue + } + var fieldSetErr error + if isUnexportedField { + fieldSetErr = fmt.Errorf( + "json: cannot set embedded pointer to unexported struct: %v", + field.Type.Elem(), + ) + } + if dec, ok := contentDec.(*structDecoder); ok { + for k, v := range dec.fieldMap { + if tags.ExistsKey(k) { + continue + } + fieldSet := &structFieldSet{ + dec: newAnonymousFieldDecoder(pdec.typ, v.offset, v.dec), + offset: field.Offset, + isTaggedKey: v.isTaggedKey, + key: k, + keyLen: int64(len(k)), + err: fieldSetErr, + } + allFields = append(allFields, fieldSet) + } + } else { + fieldSet := &structFieldSet{ + dec: pdec, + offset: field.Offset, + isTaggedKey: tag.IsTaggedKey, + key: field.Name, + keyLen: int64(len(field.Name)), + } + allFields = append(allFields, fieldSet) + } + } else { + fieldSet := &structFieldSet{ + dec: dec, + offset: field.Offset, + isTaggedKey: tag.IsTaggedKey, + key: field.Name, + keyLen: int64(len(field.Name)), + } + allFields = append(allFields, fieldSet) + } + } else { + if tag.IsString && isStringTagSupportedType(runtime.Type2RType(field.Type)) { + dec = newWrappedStringDecoder(runtime.Type2RType(field.Type), dec, structName, field.Name) + } + var key string + if tag.Key != "" { + key = tag.Key + } else { + key = field.Name + } + fieldSet := &structFieldSet{ + dec: dec, + offset: field.Offset, + isTaggedKey: tag.IsTaggedKey, + key: key, + keyLen: int64(len(key)), + } + allFields = append(allFields, fieldSet) + } + } + for _, set := range filterDuplicatedFields(allFields) { + fieldMap[set.key] = set + lower := strings.ToLower(set.key) + if _, exists := fieldMap[lower]; !exists { + // first win + fieldMap[lower] = set + } + } + delete(structTypeToDecoder, typeptr) + structDec.tryOptimize() + return structDec, nil +} + +func filterDuplicatedFields(allFields []*structFieldSet) []*structFieldSet { + fieldMap := map[string][]*structFieldSet{} + for _, field := range allFields { + fieldMap[field.key] = append(fieldMap[field.key], field) + } + duplicatedFieldMap := map[string]struct{}{} + for k, sets := range fieldMap { + sets = filterFieldSets(sets) + if len(sets) != 1 { + duplicatedFieldMap[k] = struct{}{} + } + } + + filtered := make([]*structFieldSet, 0, len(allFields)) + for _, field := range allFields { + if _, exists := duplicatedFieldMap[field.key]; exists { + continue + } + filtered = append(filtered, field) + } + return filtered +} + +func filterFieldSets(sets []*structFieldSet) []*structFieldSet { + if len(sets) == 1 { + return sets + } + filtered := make([]*structFieldSet, 0, len(sets)) + for _, set := range sets { + if set.isTaggedKey { + filtered = append(filtered, set) + } + } + return filtered +} + +func implementsUnmarshalJSONType(typ *runtime.Type) bool { + return typ.Implements(unmarshalJSONType) || typ.Implements(unmarshalJSONContextType) +} diff --git a/vendor/github.com/goccy/go-json/internal/decoder/compile_norace.go b/vendor/github.com/goccy/go-json/internal/decoder/compile_norace.go new file mode 100644 index 000000000..eb7e2b134 --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/decoder/compile_norace.go @@ -0,0 +1,29 @@ +//go:build !race +// +build !race + +package decoder + +import ( + "unsafe" + + "github.com/goccy/go-json/internal/runtime" +) + +func CompileToGetDecoder(typ *runtime.Type) (Decoder, error) { + typeptr := uintptr(unsafe.Pointer(typ)) + if typeptr > typeAddr.MaxTypeAddr { + return compileToGetDecoderSlowPath(typeptr, typ) + } + + index := (typeptr - typeAddr.BaseTypeAddr) >> typeAddr.AddrShift + if dec := cachedDecoder[index]; dec != nil { + return dec, nil + } + + dec, err := compileHead(typ, map[uintptr]Decoder{}) + if err != nil { + return nil, err + } + cachedDecoder[index] = dec + return dec, nil +} diff --git a/vendor/github.com/goccy/go-json/internal/decoder/compile_race.go b/vendor/github.com/goccy/go-json/internal/decoder/compile_race.go new file mode 100644 index 000000000..49cdda4a1 --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/decoder/compile_race.go @@ -0,0 +1,37 @@ +//go:build race +// +build race + +package decoder + +import ( + "sync" + "unsafe" + + "github.com/goccy/go-json/internal/runtime" +) + +var decMu sync.RWMutex + +func CompileToGetDecoder(typ *runtime.Type) (Decoder, error) { + typeptr := uintptr(unsafe.Pointer(typ)) + if typeptr > typeAddr.MaxTypeAddr { + return compileToGetDecoderSlowPath(typeptr, typ) + } + + index := (typeptr - typeAddr.BaseTypeAddr) >> typeAddr.AddrShift + decMu.RLock() + if dec := cachedDecoder[index]; dec != nil { + decMu.RUnlock() + return dec, nil + } + decMu.RUnlock() + + dec, err := compileHead(typ, map[uintptr]Decoder{}) + if err != nil { + return nil, err + } + decMu.Lock() + cachedDecoder[index] = dec + decMu.Unlock() + return dec, nil +} diff --git a/vendor/github.com/goccy/go-json/internal/decoder/context.go b/vendor/github.com/goccy/go-json/internal/decoder/context.go new file mode 100644 index 000000000..cb2ffdafd --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/decoder/context.go @@ -0,0 +1,254 @@ +package decoder + +import ( + "sync" + "unsafe" + + "github.com/goccy/go-json/internal/errors" +) + +type RuntimeContext struct { + Buf []byte + Option *Option +} + +var ( + runtimeContextPool = sync.Pool{ + New: func() interface{} { + return &RuntimeContext{ + Option: &Option{}, + } + }, + } +) + +func TakeRuntimeContext() *RuntimeContext { + return runtimeContextPool.Get().(*RuntimeContext) +} + +func ReleaseRuntimeContext(ctx *RuntimeContext) { + runtimeContextPool.Put(ctx) +} + +var ( + isWhiteSpace = [256]bool{} +) + +func init() { + isWhiteSpace[' '] = true + isWhiteSpace['\n'] = true + isWhiteSpace['\t'] = true + isWhiteSpace['\r'] = true +} + +func char(ptr unsafe.Pointer, offset int64) byte { + return *(*byte)(unsafe.Pointer(uintptr(ptr) + uintptr(offset))) +} + +func skipWhiteSpace(buf []byte, cursor int64) int64 { + for isWhiteSpace[buf[cursor]] { + cursor++ + } + return cursor +} + +func skipObject(buf []byte, cursor, depth int64) (int64, error) { + braceCount := 1 + for { + switch buf[cursor] { + case '{': + braceCount++ + depth++ + if depth > maxDecodeNestingDepth { + return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor) + } + case '}': + depth-- + braceCount-- + if braceCount == 0 { + return cursor + 1, nil + } + case '[': + depth++ + if depth > maxDecodeNestingDepth { + return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor) + } + case ']': + depth-- + case '"': + for { + cursor++ + switch buf[cursor] { + case '\\': + cursor++ + if buf[cursor] == nul { + return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor) + } + case '"': + goto SWITCH_OUT + case nul: + return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor) + } + } + case nul: + return 0, errors.ErrUnexpectedEndOfJSON("object of object", cursor) + } + SWITCH_OUT: + cursor++ + } +} + +func skipArray(buf []byte, cursor, depth int64) (int64, error) { + bracketCount := 1 + for { + switch buf[cursor] { + case '[': + bracketCount++ + depth++ + if depth > maxDecodeNestingDepth { + return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor) + } + case ']': + bracketCount-- + depth-- + if bracketCount == 0 { + return cursor + 1, nil + } + case '{': + depth++ + if depth > maxDecodeNestingDepth { + return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor) + } + case '}': + depth-- + case '"': + for { + cursor++ + switch buf[cursor] { + case '\\': + cursor++ + if buf[cursor] == nul { + return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor) + } + case '"': + goto SWITCH_OUT + case nul: + return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor) + } + } + case nul: + return 0, errors.ErrUnexpectedEndOfJSON("array of object", cursor) + } + SWITCH_OUT: + cursor++ + } +} + +func skipValue(buf []byte, cursor, depth int64) (int64, error) { + for { + switch buf[cursor] { + case ' ', '\t', '\n', '\r': + cursor++ + continue + case '{': + return skipObject(buf, cursor+1, depth+1) + case '[': + return skipArray(buf, cursor+1, depth+1) + case '"': + for { + cursor++ + switch buf[cursor] { + case '\\': + cursor++ + if buf[cursor] == nul { + return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor) + } + case '"': + return cursor + 1, nil + case nul: + return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor) + } + } + case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + for { + cursor++ + if floatTable[buf[cursor]] { + continue + } + break + } + return cursor, nil + case 't': + if err := validateTrue(buf, cursor); err != nil { + return 0, err + } + cursor += 4 + return cursor, nil + case 'f': + if err := validateFalse(buf, cursor); err != nil { + return 0, err + } + cursor += 5 + return cursor, nil + case 'n': + if err := validateNull(buf, cursor); err != nil { + return 0, err + } + cursor += 4 + return cursor, nil + default: + return cursor, errors.ErrUnexpectedEndOfJSON("null", cursor) + } + } +} + +func validateTrue(buf []byte, cursor int64) error { + if cursor+3 >= int64(len(buf)) { + return errors.ErrUnexpectedEndOfJSON("true", cursor) + } + if buf[cursor+1] != 'r' { + return errors.ErrInvalidCharacter(buf[cursor+1], "true", cursor) + } + if buf[cursor+2] != 'u' { + return errors.ErrInvalidCharacter(buf[cursor+2], "true", cursor) + } + if buf[cursor+3] != 'e' { + return errors.ErrInvalidCharacter(buf[cursor+3], "true", cursor) + } + return nil +} + +func validateFalse(buf []byte, cursor int64) error { + if cursor+4 >= int64(len(buf)) { + return errors.ErrUnexpectedEndOfJSON("false", cursor) + } + if buf[cursor+1] != 'a' { + return errors.ErrInvalidCharacter(buf[cursor+1], "false", cursor) + } + if buf[cursor+2] != 'l' { + return errors.ErrInvalidCharacter(buf[cursor+2], "false", cursor) + } + if buf[cursor+3] != 's' { + return errors.ErrInvalidCharacter(buf[cursor+3], "false", cursor) + } + if buf[cursor+4] != 'e' { + return errors.ErrInvalidCharacter(buf[cursor+4], "false", cursor) + } + return nil +} + +func validateNull(buf []byte, cursor int64) error { + if cursor+3 >= int64(len(buf)) { + return errors.ErrUnexpectedEndOfJSON("null", cursor) + } + if buf[cursor+1] != 'u' { + return errors.ErrInvalidCharacter(buf[cursor+1], "null", cursor) + } + if buf[cursor+2] != 'l' { + return errors.ErrInvalidCharacter(buf[cursor+2], "null", cursor) + } + if buf[cursor+3] != 'l' { + return errors.ErrInvalidCharacter(buf[cursor+3], "null", cursor) + } + return nil +} diff --git a/vendor/github.com/goccy/go-json/internal/decoder/float.go b/vendor/github.com/goccy/go-json/internal/decoder/float.go new file mode 100644 index 000000000..9b2eb8b35 --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/decoder/float.go @@ -0,0 +1,170 @@ +package decoder + +import ( + "strconv" + "unsafe" + + "github.com/goccy/go-json/internal/errors" +) + +type floatDecoder struct { + op func(unsafe.Pointer, float64) + structName string + fieldName string +} + +func newFloatDecoder(structName, fieldName string, op func(unsafe.Pointer, float64)) *floatDecoder { + return &floatDecoder{op: op, structName: structName, fieldName: fieldName} +} + +var ( + floatTable = [256]bool{ + '0': true, + '1': true, + '2': true, + '3': true, + '4': true, + '5': true, + '6': true, + '7': true, + '8': true, + '9': true, + '.': true, + 'e': true, + 'E': true, + '+': true, + '-': true, + } + + validEndNumberChar = [256]bool{ + nul: true, + ' ': true, + '\t': true, + '\r': true, + '\n': true, + ',': true, + ':': true, + '}': true, + ']': true, + } +) + +func floatBytes(s *Stream) []byte { + start := s.cursor + for { + s.cursor++ + if floatTable[s.char()] { + continue + } else if s.char() == nul { + if s.read() { + s.cursor-- // for retry current character + continue + } + } + break + } + return s.buf[start:s.cursor] +} + +func (d *floatDecoder) decodeStreamByte(s *Stream) ([]byte, error) { + for { + switch s.char() { + case ' ', '\n', '\t', '\r': + s.cursor++ + continue + case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + return floatBytes(s), nil + case 'n': + if err := nullBytes(s); err != nil { + return nil, err + } + return nil, nil + case nul: + if s.read() { + continue + } + goto ERROR + default: + goto ERROR + } + } +ERROR: + return nil, errors.ErrUnexpectedEndOfJSON("float", s.totalOffset()) +} + +func (d *floatDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) { + for { + switch buf[cursor] { + case ' ', '\n', '\t', '\r': + cursor++ + continue + case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + start := cursor + cursor++ + for floatTable[buf[cursor]] { + cursor++ + } + num := buf[start:cursor] + return num, cursor, nil + case 'n': + if err := validateNull(buf, cursor); err != nil { + return nil, 0, err + } + cursor += 4 + return nil, cursor, nil + default: + return nil, 0, errors.ErrUnexpectedEndOfJSON("float", cursor) + } + } +} + +func (d *floatDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error { + bytes, err := d.decodeStreamByte(s) + if err != nil { + return err + } + if bytes == nil { + return nil + } + str := *(*string)(unsafe.Pointer(&bytes)) + f64, err := strconv.ParseFloat(str, 64) + if err != nil { + return errors.ErrSyntax(err.Error(), s.totalOffset()) + } + d.op(p, f64) + return nil +} + +func (d *floatDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { + buf := ctx.Buf + bytes, c, err := d.decodeByte(buf, cursor) + if err != nil { + return 0, err + } + if bytes == nil { + return c, nil + } + cursor = c + if !validEndNumberChar[buf[cursor]] { + return 0, errors.ErrUnexpectedEndOfJSON("float", cursor) + } + s := *(*string)(unsafe.Pointer(&bytes)) + f64, err := strconv.ParseFloat(s, 64) + if err != nil { + return 0, errors.ErrSyntax(err.Error(), cursor) + } + d.op(p, f64) + return cursor, nil +} + +func (d *floatDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) { + buf := ctx.Buf + bytes, c, err := d.decodeByte(buf, cursor) + if err != nil { + return nil, 0, err + } + if bytes == nil { + return [][]byte{nullbytes}, c, nil + } + return [][]byte{bytes}, c, nil +} diff --git a/vendor/github.com/goccy/go-json/internal/decoder/func.go b/vendor/github.com/goccy/go-json/internal/decoder/func.go new file mode 100644 index 000000000..4cc12ca81 --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/decoder/func.go @@ -0,0 +1,146 @@ +package decoder + +import ( + "bytes" + "fmt" + "unsafe" + + "github.com/goccy/go-json/internal/errors" + "github.com/goccy/go-json/internal/runtime" +) + +type funcDecoder struct { + typ *runtime.Type + structName string + fieldName string +} + +func newFuncDecoder(typ *runtime.Type, structName, fieldName string) *funcDecoder { + fnDecoder := &funcDecoder{typ, structName, fieldName} + return fnDecoder +} + +func (d *funcDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error { + s.skipWhiteSpace() + start := s.cursor + if err := s.skipValue(depth); err != nil { + return err + } + src := s.buf[start:s.cursor] + if len(src) > 0 { + switch src[0] { + case '"': + return &errors.UnmarshalTypeError{ + Value: "string", + Type: runtime.RType2Type(d.typ), + Offset: s.totalOffset(), + } + case '[': + return &errors.UnmarshalTypeError{ + Value: "array", + Type: runtime.RType2Type(d.typ), + Offset: s.totalOffset(), + } + case '{': + return &errors.UnmarshalTypeError{ + Value: "object", + Type: runtime.RType2Type(d.typ), + Offset: s.totalOffset(), + } + case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + return &errors.UnmarshalTypeError{ + Value: "number", + Type: runtime.RType2Type(d.typ), + Offset: s.totalOffset(), + } + case 'n': + if err := nullBytes(s); err != nil { + return err + } + *(*unsafe.Pointer)(p) = nil + return nil + case 't': + if err := trueBytes(s); err == nil { + return &errors.UnmarshalTypeError{ + Value: "boolean", + Type: runtime.RType2Type(d.typ), + Offset: s.totalOffset(), + } + } + case 'f': + if err := falseBytes(s); err == nil { + return &errors.UnmarshalTypeError{ + Value: "boolean", + Type: runtime.RType2Type(d.typ), + Offset: s.totalOffset(), + } + } + } + } + return errors.ErrInvalidBeginningOfValue(s.buf[s.cursor], s.totalOffset()) +} + +func (d *funcDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { + buf := ctx.Buf + cursor = skipWhiteSpace(buf, cursor) + start := cursor + end, err := skipValue(buf, cursor, depth) + if err != nil { + return 0, err + } + src := buf[start:end] + if len(src) > 0 { + switch src[0] { + case '"': + return 0, &errors.UnmarshalTypeError{ + Value: "string", + Type: runtime.RType2Type(d.typ), + Offset: start, + } + case '[': + return 0, &errors.UnmarshalTypeError{ + Value: "array", + Type: runtime.RType2Type(d.typ), + Offset: start, + } + case '{': + return 0, &errors.UnmarshalTypeError{ + Value: "object", + Type: runtime.RType2Type(d.typ), + Offset: start, + } + case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + return 0, &errors.UnmarshalTypeError{ + Value: "number", + Type: runtime.RType2Type(d.typ), + Offset: start, + } + case 'n': + if bytes.Equal(src, nullbytes) { + *(*unsafe.Pointer)(p) = nil + return end, nil + } + case 't': + if err := validateTrue(buf, start); err == nil { + return 0, &errors.UnmarshalTypeError{ + Value: "boolean", + Type: runtime.RType2Type(d.typ), + Offset: start, + } + } + case 'f': + if err := validateFalse(buf, start); err == nil { + return 0, &errors.UnmarshalTypeError{ + Value: "boolean", + Type: runtime.RType2Type(d.typ), + Offset: start, + } + } + } + } + return cursor, errors.ErrInvalidBeginningOfValue(buf[cursor], cursor) +} + +func (d *funcDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) { + return nil, 0, fmt.Errorf("json: func decoder does not support decode path") +} diff --git a/vendor/github.com/goccy/go-json/internal/decoder/int.go b/vendor/github.com/goccy/go-json/internal/decoder/int.go new file mode 100644 index 000000000..1a7f08199 --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/decoder/int.go @@ -0,0 +1,246 @@ +package decoder + +import ( + "fmt" + "reflect" + "unsafe" + + "github.com/goccy/go-json/internal/errors" + "github.com/goccy/go-json/internal/runtime" +) + +type intDecoder struct { + typ *runtime.Type + kind reflect.Kind + op func(unsafe.Pointer, int64) + structName string + fieldName string +} + +func newIntDecoder(typ *runtime.Type, structName, fieldName string, op func(unsafe.Pointer, int64)) *intDecoder { + return &intDecoder{ + typ: typ, + kind: typ.Kind(), + op: op, + structName: structName, + fieldName: fieldName, + } +} + +func (d *intDecoder) typeError(buf []byte, offset int64) *errors.UnmarshalTypeError { + return &errors.UnmarshalTypeError{ + Value: fmt.Sprintf("number %s", string(buf)), + Type: runtime.RType2Type(d.typ), + Struct: d.structName, + Field: d.fieldName, + Offset: offset, + } +} + +var ( + pow10i64 = [...]int64{ + 1e00, 1e01, 1e02, 1e03, 1e04, 1e05, 1e06, 1e07, 1e08, 1e09, + 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, + } + pow10i64Len = len(pow10i64) +) + +func (d *intDecoder) parseInt(b []byte) (int64, error) { + isNegative := false + if b[0] == '-' { + b = b[1:] + isNegative = true + } + maxDigit := len(b) + if maxDigit > pow10i64Len { + return 0, fmt.Errorf("invalid length of number") + } + sum := int64(0) + for i := 0; i < maxDigit; i++ { + c := int64(b[i]) - 48 + digitValue := pow10i64[maxDigit-i-1] + sum += c * digitValue + } + if isNegative { + return -1 * sum, nil + } + return sum, nil +} + +var ( + numTable = [256]bool{ + '0': true, + '1': true, + '2': true, + '3': true, + '4': true, + '5': true, + '6': true, + '7': true, + '8': true, + '9': true, + } +) + +var ( + numZeroBuf = []byte{'0'} +) + +func (d *intDecoder) decodeStreamByte(s *Stream) ([]byte, error) { + for { + switch s.char() { + case ' ', '\n', '\t', '\r': + s.cursor++ + continue + case '-': + start := s.cursor + for { + s.cursor++ + if numTable[s.char()] { + continue + } else if s.char() == nul { + if s.read() { + s.cursor-- // for retry current character + continue + } + } + break + } + num := s.buf[start:s.cursor] + if len(num) < 2 { + goto ERROR + } + return num, nil + case '0': + s.cursor++ + return numZeroBuf, nil + case '1', '2', '3', '4', '5', '6', '7', '8', '9': + start := s.cursor + for { + s.cursor++ + if numTable[s.char()] { + continue + } else if s.char() == nul { + if s.read() { + s.cursor-- // for retry current character + continue + } + } + break + } + num := s.buf[start:s.cursor] + return num, nil + case 'n': + if err := nullBytes(s); err != nil { + return nil, err + } + return nil, nil + case nul: + if s.read() { + continue + } + goto ERROR + default: + return nil, d.typeError([]byte{s.char()}, s.totalOffset()) + } + } +ERROR: + return nil, errors.ErrUnexpectedEndOfJSON("number(integer)", s.totalOffset()) +} + +func (d *intDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) { + b := (*sliceHeader)(unsafe.Pointer(&buf)).data + for { + switch char(b, cursor) { + case ' ', '\n', '\t', '\r': + cursor++ + continue + case '0': + cursor++ + return numZeroBuf, cursor, nil + case '-', '1', '2', '3', '4', '5', '6', '7', '8', '9': + start := cursor + cursor++ + for numTable[char(b, cursor)] { + cursor++ + } + num := buf[start:cursor] + return num, cursor, nil + case 'n': + if err := validateNull(buf, cursor); err != nil { + return nil, 0, err + } + cursor += 4 + return nil, cursor, nil + default: + return nil, 0, d.typeError([]byte{char(b, cursor)}, cursor) + } + } +} + +func (d *intDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error { + bytes, err := d.decodeStreamByte(s) + if err != nil { + return err + } + if bytes == nil { + return nil + } + i64, err := d.parseInt(bytes) + if err != nil { + return d.typeError(bytes, s.totalOffset()) + } + switch d.kind { + case reflect.Int8: + if i64 < -1*(1<<7) || (1<<7) <= i64 { + return d.typeError(bytes, s.totalOffset()) + } + case reflect.Int16: + if i64 < -1*(1<<15) || (1<<15) <= i64 { + return d.typeError(bytes, s.totalOffset()) + } + case reflect.Int32: + if i64 < -1*(1<<31) || (1<<31) <= i64 { + return d.typeError(bytes, s.totalOffset()) + } + } + d.op(p, i64) + s.reset() + return nil +} + +func (d *intDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { + bytes, c, err := d.decodeByte(ctx.Buf, cursor) + if err != nil { + return 0, err + } + if bytes == nil { + return c, nil + } + cursor = c + + i64, err := d.parseInt(bytes) + if err != nil { + return 0, d.typeError(bytes, cursor) + } + switch d.kind { + case reflect.Int8: + if i64 < -1*(1<<7) || (1<<7) <= i64 { + return 0, d.typeError(bytes, cursor) + } + case reflect.Int16: + if i64 < -1*(1<<15) || (1<<15) <= i64 { + return 0, d.typeError(bytes, cursor) + } + case reflect.Int32: + if i64 < -1*(1<<31) || (1<<31) <= i64 { + return 0, d.typeError(bytes, cursor) + } + } + d.op(p, i64) + return cursor, nil +} + +func (d *intDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) { + return nil, 0, fmt.Errorf("json: int decoder does not support decode path") +} diff --git a/vendor/github.com/goccy/go-json/internal/decoder/interface.go b/vendor/github.com/goccy/go-json/internal/decoder/interface.go new file mode 100644 index 000000000..45c69ab8c --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/decoder/interface.go @@ -0,0 +1,528 @@ +package decoder + +import ( + "bytes" + "encoding" + "encoding/json" + "reflect" + "unsafe" + + "github.com/goccy/go-json/internal/errors" + "github.com/goccy/go-json/internal/runtime" +) + +type interfaceDecoder struct { + typ *runtime.Type + structName string + fieldName string + sliceDecoder *sliceDecoder + mapDecoder *mapDecoder + floatDecoder *floatDecoder + numberDecoder *numberDecoder + stringDecoder *stringDecoder +} + +func newEmptyInterfaceDecoder(structName, fieldName string) *interfaceDecoder { + ifaceDecoder := &interfaceDecoder{ + typ: emptyInterfaceType, + structName: structName, + fieldName: fieldName, + floatDecoder: newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) { + *(*interface{})(p) = v + }), + numberDecoder: newNumberDecoder(structName, fieldName, func(p unsafe.Pointer, v json.Number) { + *(*interface{})(p) = v + }), + stringDecoder: newStringDecoder(structName, fieldName), + } + ifaceDecoder.sliceDecoder = newSliceDecoder( + ifaceDecoder, + emptyInterfaceType, + emptyInterfaceType.Size(), + structName, fieldName, + ) + ifaceDecoder.mapDecoder = newMapDecoder( + interfaceMapType, + stringType, + ifaceDecoder.stringDecoder, + interfaceMapType.Elem(), + ifaceDecoder, + structName, + fieldName, + ) + return ifaceDecoder +} + +func newInterfaceDecoder(typ *runtime.Type, structName, fieldName string) *interfaceDecoder { + emptyIfaceDecoder := newEmptyInterfaceDecoder(structName, fieldName) + stringDecoder := newStringDecoder(structName, fieldName) + return &interfaceDecoder{ + typ: typ, + structName: structName, + fieldName: fieldName, + sliceDecoder: newSliceDecoder( + emptyIfaceDecoder, + emptyInterfaceType, + emptyInterfaceType.Size(), + structName, fieldName, + ), + mapDecoder: newMapDecoder( + interfaceMapType, + stringType, + stringDecoder, + interfaceMapType.Elem(), + emptyIfaceDecoder, + structName, + fieldName, + ), + floatDecoder: newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) { + *(*interface{})(p) = v + }), + numberDecoder: newNumberDecoder(structName, fieldName, func(p unsafe.Pointer, v json.Number) { + *(*interface{})(p) = v + }), + stringDecoder: stringDecoder, + } +} + +func (d *interfaceDecoder) numDecoder(s *Stream) Decoder { + if s.UseNumber { + return d.numberDecoder + } + return d.floatDecoder +} + +var ( + emptyInterfaceType = runtime.Type2RType(reflect.TypeOf((*interface{})(nil)).Elem()) + EmptyInterfaceType = emptyInterfaceType + interfaceMapType = runtime.Type2RType( + reflect.TypeOf((*map[string]interface{})(nil)).Elem(), + ) + stringType = runtime.Type2RType( + reflect.TypeOf(""), + ) +) + +func decodeStreamUnmarshaler(s *Stream, depth int64, unmarshaler json.Unmarshaler) error { + start := s.cursor + if err := s.skipValue(depth); err != nil { + return err + } + src := s.buf[start:s.cursor] + dst := make([]byte, len(src)) + copy(dst, src) + + if err := unmarshaler.UnmarshalJSON(dst); err != nil { + return err + } + return nil +} + +func decodeStreamUnmarshalerContext(s *Stream, depth int64, unmarshaler unmarshalerContext) error { + start := s.cursor + if err := s.skipValue(depth); err != nil { + return err + } + src := s.buf[start:s.cursor] + dst := make([]byte, len(src)) + copy(dst, src) + + if err := unmarshaler.UnmarshalJSON(s.Option.Context, dst); err != nil { + return err + } + return nil +} + +func decodeUnmarshaler(buf []byte, cursor, depth int64, unmarshaler json.Unmarshaler) (int64, error) { + cursor = skipWhiteSpace(buf, cursor) + start := cursor + end, err := skipValue(buf, cursor, depth) + if err != nil { + return 0, err + } + src := buf[start:end] + dst := make([]byte, len(src)) + copy(dst, src) + + if err := unmarshaler.UnmarshalJSON(dst); err != nil { + return 0, err + } + return end, nil +} + +func decodeUnmarshalerContext(ctx *RuntimeContext, buf []byte, cursor, depth int64, unmarshaler unmarshalerContext) (int64, error) { + cursor = skipWhiteSpace(buf, cursor) + start := cursor + end, err := skipValue(buf, cursor, depth) + if err != nil { + return 0, err + } + src := buf[start:end] + dst := make([]byte, len(src)) + copy(dst, src) + + if err := unmarshaler.UnmarshalJSON(ctx.Option.Context, dst); err != nil { + return 0, err + } + return end, nil +} + +func decodeStreamTextUnmarshaler(s *Stream, depth int64, unmarshaler encoding.TextUnmarshaler, p unsafe.Pointer) error { + start := s.cursor + if err := s.skipValue(depth); err != nil { + return err + } + src := s.buf[start:s.cursor] + if bytes.Equal(src, nullbytes) { + *(*unsafe.Pointer)(p) = nil + return nil + } + + dst := make([]byte, len(src)) + copy(dst, src) + + if err := unmarshaler.UnmarshalText(dst); err != nil { + return err + } + return nil +} + +func decodeTextUnmarshaler(buf []byte, cursor, depth int64, unmarshaler encoding.TextUnmarshaler, p unsafe.Pointer) (int64, error) { + cursor = skipWhiteSpace(buf, cursor) + start := cursor + end, err := skipValue(buf, cursor, depth) + if err != nil { + return 0, err + } + src := buf[start:end] + if bytes.Equal(src, nullbytes) { + *(*unsafe.Pointer)(p) = nil + return end, nil + } + if s, ok := unquoteBytes(src); ok { + src = s + } + if err := unmarshaler.UnmarshalText(src); err != nil { + return 0, err + } + return end, nil +} + +func (d *interfaceDecoder) decodeStreamEmptyInterface(s *Stream, depth int64, p unsafe.Pointer) error { + c := s.skipWhiteSpace() + for { + switch c { + case '{': + var v map[string]interface{} + ptr := unsafe.Pointer(&v) + if err := d.mapDecoder.DecodeStream(s, depth, ptr); err != nil { + return err + } + *(*interface{})(p) = v + return nil + case '[': + var v []interface{} + ptr := unsafe.Pointer(&v) + if err := d.sliceDecoder.DecodeStream(s, depth, ptr); err != nil { + return err + } + *(*interface{})(p) = v + return nil + case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + return d.numDecoder(s).DecodeStream(s, depth, p) + case '"': + s.cursor++ + start := s.cursor + for { + switch s.char() { + case '\\': + if _, err := decodeEscapeString(s, nil); err != nil { + return err + } + case '"': + literal := s.buf[start:s.cursor] + s.cursor++ + *(*interface{})(p) = string(literal) + return nil + case nul: + if s.read() { + continue + } + return errors.ErrUnexpectedEndOfJSON("string", s.totalOffset()) + } + s.cursor++ + } + case 't': + if err := trueBytes(s); err != nil { + return err + } + **(**interface{})(unsafe.Pointer(&p)) = true + return nil + case 'f': + if err := falseBytes(s); err != nil { + return err + } + **(**interface{})(unsafe.Pointer(&p)) = false + return nil + case 'n': + if err := nullBytes(s); err != nil { + return err + } + *(*interface{})(p) = nil + return nil + case nul: + if s.read() { + c = s.char() + continue + } + } + break + } + return errors.ErrInvalidBeginningOfValue(c, s.totalOffset()) +} + +type emptyInterface struct { + typ *runtime.Type + ptr unsafe.Pointer +} + +func (d *interfaceDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error { + runtimeInterfaceValue := *(*interface{})(unsafe.Pointer(&emptyInterface{ + typ: d.typ, + ptr: p, + })) + rv := reflect.ValueOf(runtimeInterfaceValue) + if rv.NumMethod() > 0 && rv.CanInterface() { + if u, ok := rv.Interface().(unmarshalerContext); ok { + return decodeStreamUnmarshalerContext(s, depth, u) + } + if u, ok := rv.Interface().(json.Unmarshaler); ok { + return decodeStreamUnmarshaler(s, depth, u) + } + if u, ok := rv.Interface().(encoding.TextUnmarshaler); ok { + return decodeStreamTextUnmarshaler(s, depth, u, p) + } + if s.skipWhiteSpace() == 'n' { + if err := nullBytes(s); err != nil { + return err + } + *(*interface{})(p) = nil + return nil + } + return d.errUnmarshalType(rv.Type(), s.totalOffset()) + } + iface := rv.Interface() + ifaceHeader := (*emptyInterface)(unsafe.Pointer(&iface)) + typ := ifaceHeader.typ + if ifaceHeader.ptr == nil || d.typ == typ || typ == nil { + // concrete type is empty interface + return d.decodeStreamEmptyInterface(s, depth, p) + } + if typ.Kind() == reflect.Ptr && typ.Elem() == d.typ || typ.Kind() != reflect.Ptr { + return d.decodeStreamEmptyInterface(s, depth, p) + } + if s.skipWhiteSpace() == 'n' { + if err := nullBytes(s); err != nil { + return err + } + *(*interface{})(p) = nil + return nil + } + decoder, err := CompileToGetDecoder(typ) + if err != nil { + return err + } + return decoder.DecodeStream(s, depth, ifaceHeader.ptr) +} + +func (d *interfaceDecoder) errUnmarshalType(typ reflect.Type, offset int64) *errors.UnmarshalTypeError { + return &errors.UnmarshalTypeError{ + Value: typ.String(), + Type: typ, + Offset: offset, + Struct: d.structName, + Field: d.fieldName, + } +} + +func (d *interfaceDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { + buf := ctx.Buf + runtimeInterfaceValue := *(*interface{})(unsafe.Pointer(&emptyInterface{ + typ: d.typ, + ptr: p, + })) + rv := reflect.ValueOf(runtimeInterfaceValue) + if rv.NumMethod() > 0 && rv.CanInterface() { + if u, ok := rv.Interface().(unmarshalerContext); ok { + return decodeUnmarshalerContext(ctx, buf, cursor, depth, u) + } + if u, ok := rv.Interface().(json.Unmarshaler); ok { + return decodeUnmarshaler(buf, cursor, depth, u) + } + if u, ok := rv.Interface().(encoding.TextUnmarshaler); ok { + return decodeTextUnmarshaler(buf, cursor, depth, u, p) + } + cursor = skipWhiteSpace(buf, cursor) + if buf[cursor] == 'n' { + if err := validateNull(buf, cursor); err != nil { + return 0, err + } + cursor += 4 + **(**interface{})(unsafe.Pointer(&p)) = nil + return cursor, nil + } + return 0, d.errUnmarshalType(rv.Type(), cursor) + } + + iface := rv.Interface() + ifaceHeader := (*emptyInterface)(unsafe.Pointer(&iface)) + typ := ifaceHeader.typ + if ifaceHeader.ptr == nil || d.typ == typ || typ == nil { + // concrete type is empty interface + return d.decodeEmptyInterface(ctx, cursor, depth, p) + } + if typ.Kind() == reflect.Ptr && typ.Elem() == d.typ || typ.Kind() != reflect.Ptr { + return d.decodeEmptyInterface(ctx, cursor, depth, p) + } + cursor = skipWhiteSpace(buf, cursor) + if buf[cursor] == 'n' { + if err := validateNull(buf, cursor); err != nil { + return 0, err + } + cursor += 4 + **(**interface{})(unsafe.Pointer(&p)) = nil + return cursor, nil + } + decoder, err := CompileToGetDecoder(typ) + if err != nil { + return 0, err + } + return decoder.Decode(ctx, cursor, depth, ifaceHeader.ptr) +} + +func (d *interfaceDecoder) decodeEmptyInterface(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { + buf := ctx.Buf + cursor = skipWhiteSpace(buf, cursor) + switch buf[cursor] { + case '{': + var v map[string]interface{} + ptr := unsafe.Pointer(&v) + cursor, err := d.mapDecoder.Decode(ctx, cursor, depth, ptr) + if err != nil { + return 0, err + } + **(**interface{})(unsafe.Pointer(&p)) = v + return cursor, nil + case '[': + var v []interface{} + ptr := unsafe.Pointer(&v) + cursor, err := d.sliceDecoder.Decode(ctx, cursor, depth, ptr) + if err != nil { + return 0, err + } + **(**interface{})(unsafe.Pointer(&p)) = v + return cursor, nil + case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + return d.floatDecoder.Decode(ctx, cursor, depth, p) + case '"': + var v string + ptr := unsafe.Pointer(&v) + cursor, err := d.stringDecoder.Decode(ctx, cursor, depth, ptr) + if err != nil { + return 0, err + } + **(**interface{})(unsafe.Pointer(&p)) = v + return cursor, nil + case 't': + if err := validateTrue(buf, cursor); err != nil { + return 0, err + } + cursor += 4 + **(**interface{})(unsafe.Pointer(&p)) = true + return cursor, nil + case 'f': + if err := validateFalse(buf, cursor); err != nil { + return 0, err + } + cursor += 5 + **(**interface{})(unsafe.Pointer(&p)) = false + return cursor, nil + case 'n': + if err := validateNull(buf, cursor); err != nil { + return 0, err + } + cursor += 4 + **(**interface{})(unsafe.Pointer(&p)) = nil + return cursor, nil + } + return cursor, errors.ErrInvalidBeginningOfValue(buf[cursor], cursor) +} + +func NewPathDecoder() Decoder { + ifaceDecoder := &interfaceDecoder{ + typ: emptyInterfaceType, + structName: "", + fieldName: "", + floatDecoder: newFloatDecoder("", "", func(p unsafe.Pointer, v float64) { + *(*interface{})(p) = v + }), + numberDecoder: newNumberDecoder("", "", func(p unsafe.Pointer, v json.Number) { + *(*interface{})(p) = v + }), + stringDecoder: newStringDecoder("", ""), + } + ifaceDecoder.sliceDecoder = newSliceDecoder( + ifaceDecoder, + emptyInterfaceType, + emptyInterfaceType.Size(), + "", "", + ) + ifaceDecoder.mapDecoder = newMapDecoder( + interfaceMapType, + stringType, + ifaceDecoder.stringDecoder, + interfaceMapType.Elem(), + ifaceDecoder, + "", "", + ) + return ifaceDecoder +} + +var ( + truebytes = []byte("true") + falsebytes = []byte("false") +) + +func (d *interfaceDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) { + buf := ctx.Buf + cursor = skipWhiteSpace(buf, cursor) + switch buf[cursor] { + case '{': + return d.mapDecoder.DecodePath(ctx, cursor, depth) + case '[': + return d.sliceDecoder.DecodePath(ctx, cursor, depth) + case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + return d.floatDecoder.DecodePath(ctx, cursor, depth) + case '"': + return d.stringDecoder.DecodePath(ctx, cursor, depth) + case 't': + if err := validateTrue(buf, cursor); err != nil { + return nil, 0, err + } + cursor += 4 + return [][]byte{truebytes}, cursor, nil + case 'f': + if err := validateFalse(buf, cursor); err != nil { + return nil, 0, err + } + cursor += 5 + return [][]byte{falsebytes}, cursor, nil + case 'n': + if err := validateNull(buf, cursor); err != nil { + return nil, 0, err + } + cursor += 4 + return [][]byte{nullbytes}, cursor, nil + } + return nil, cursor, errors.ErrInvalidBeginningOfValue(buf[cursor], cursor) +} diff --git a/vendor/github.com/goccy/go-json/internal/decoder/invalid.go b/vendor/github.com/goccy/go-json/internal/decoder/invalid.go new file mode 100644 index 000000000..4c9721b09 --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/decoder/invalid.go @@ -0,0 +1,55 @@ +package decoder + +import ( + "reflect" + "unsafe" + + "github.com/goccy/go-json/internal/errors" + "github.com/goccy/go-json/internal/runtime" +) + +type invalidDecoder struct { + typ *runtime.Type + kind reflect.Kind + structName string + fieldName string +} + +func newInvalidDecoder(typ *runtime.Type, structName, fieldName string) *invalidDecoder { + return &invalidDecoder{ + typ: typ, + kind: typ.Kind(), + structName: structName, + fieldName: fieldName, + } +} + +func (d *invalidDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error { + return &errors.UnmarshalTypeError{ + Value: "object", + Type: runtime.RType2Type(d.typ), + Offset: s.totalOffset(), + Struct: d.structName, + Field: d.fieldName, + } +} + +func (d *invalidDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { + return 0, &errors.UnmarshalTypeError{ + Value: "object", + Type: runtime.RType2Type(d.typ), + Offset: cursor, + Struct: d.structName, + Field: d.fieldName, + } +} + +func (d *invalidDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) { + return nil, 0, &errors.UnmarshalTypeError{ + Value: "object", + Type: runtime.RType2Type(d.typ), + Offset: cursor, + Struct: d.structName, + Field: d.fieldName, + } +} diff --git a/vendor/github.com/goccy/go-json/internal/decoder/map.go b/vendor/github.com/goccy/go-json/internal/decoder/map.go new file mode 100644 index 000000000..07a9caea6 --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/decoder/map.go @@ -0,0 +1,280 @@ +package decoder + +import ( + "reflect" + "unsafe" + + "github.com/goccy/go-json/internal/errors" + "github.com/goccy/go-json/internal/runtime" +) + +type mapDecoder struct { + mapType *runtime.Type + keyType *runtime.Type + valueType *runtime.Type + canUseAssignFaststrType bool + keyDecoder Decoder + valueDecoder Decoder + structName string + fieldName string +} + +func newMapDecoder(mapType *runtime.Type, keyType *runtime.Type, keyDec Decoder, valueType *runtime.Type, valueDec Decoder, structName, fieldName string) *mapDecoder { + return &mapDecoder{ + mapType: mapType, + keyDecoder: keyDec, + keyType: keyType, + canUseAssignFaststrType: canUseAssignFaststrType(keyType, valueType), + valueType: valueType, + valueDecoder: valueDec, + structName: structName, + fieldName: fieldName, + } +} + +const ( + mapMaxElemSize = 128 +) + +// See detail: https://github.com/goccy/go-json/pull/283 +func canUseAssignFaststrType(key *runtime.Type, value *runtime.Type) bool { + indirectElem := value.Size() > mapMaxElemSize + if indirectElem { + return false + } + return key.Kind() == reflect.String +} + +//go:linkname makemap reflect.makemap +func makemap(*runtime.Type, int) unsafe.Pointer + +//nolint:golint +//go:linkname mapassign_faststr runtime.mapassign_faststr +//go:noescape +func mapassign_faststr(t *runtime.Type, m unsafe.Pointer, s string) unsafe.Pointer + +//go:linkname mapassign reflect.mapassign +//go:noescape +func mapassign(t *runtime.Type, m unsafe.Pointer, k, v unsafe.Pointer) + +func (d *mapDecoder) mapassign(t *runtime.Type, m, k, v unsafe.Pointer) { + if d.canUseAssignFaststrType { + mapV := mapassign_faststr(t, m, *(*string)(k)) + typedmemmove(d.valueType, mapV, v) + } else { + mapassign(t, m, k, v) + } +} + +func (d *mapDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error { + depth++ + if depth > maxDecodeNestingDepth { + return errors.ErrExceededMaxDepth(s.char(), s.cursor) + } + + switch s.skipWhiteSpace() { + case 'n': + if err := nullBytes(s); err != nil { + return err + } + **(**unsafe.Pointer)(unsafe.Pointer(&p)) = nil + return nil + case '{': + default: + return errors.ErrExpected("{ character for map value", s.totalOffset()) + } + mapValue := *(*unsafe.Pointer)(p) + if mapValue == nil { + mapValue = makemap(d.mapType, 0) + } + s.cursor++ + if s.skipWhiteSpace() == '}' { + *(*unsafe.Pointer)(p) = mapValue + s.cursor++ + return nil + } + for { + k := unsafe_New(d.keyType) + if err := d.keyDecoder.DecodeStream(s, depth, k); err != nil { + return err + } + s.skipWhiteSpace() + if !s.equalChar(':') { + return errors.ErrExpected("colon after object key", s.totalOffset()) + } + s.cursor++ + v := unsafe_New(d.valueType) + if err := d.valueDecoder.DecodeStream(s, depth, v); err != nil { + return err + } + d.mapassign(d.mapType, mapValue, k, v) + s.skipWhiteSpace() + if s.equalChar('}') { + **(**unsafe.Pointer)(unsafe.Pointer(&p)) = mapValue + s.cursor++ + return nil + } + if !s.equalChar(',') { + return errors.ErrExpected("comma after object value", s.totalOffset()) + } + s.cursor++ + } +} + +func (d *mapDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { + buf := ctx.Buf + depth++ + if depth > maxDecodeNestingDepth { + return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor) + } + + cursor = skipWhiteSpace(buf, cursor) + buflen := int64(len(buf)) + if buflen < 2 { + return 0, errors.ErrExpected("{} for map", cursor) + } + switch buf[cursor] { + case 'n': + if err := validateNull(buf, cursor); err != nil { + return 0, err + } + cursor += 4 + **(**unsafe.Pointer)(unsafe.Pointer(&p)) = nil + return cursor, nil + case '{': + default: + return 0, errors.ErrExpected("{ character for map value", cursor) + } + cursor++ + cursor = skipWhiteSpace(buf, cursor) + mapValue := *(*unsafe.Pointer)(p) + if mapValue == nil { + mapValue = makemap(d.mapType, 0) + } + if buf[cursor] == '}' { + **(**unsafe.Pointer)(unsafe.Pointer(&p)) = mapValue + cursor++ + return cursor, nil + } + for { + k := unsafe_New(d.keyType) + keyCursor, err := d.keyDecoder.Decode(ctx, cursor, depth, k) + if err != nil { + return 0, err + } + cursor = skipWhiteSpace(buf, keyCursor) + if buf[cursor] != ':' { + return 0, errors.ErrExpected("colon after object key", cursor) + } + cursor++ + v := unsafe_New(d.valueType) + valueCursor, err := d.valueDecoder.Decode(ctx, cursor, depth, v) + if err != nil { + return 0, err + } + d.mapassign(d.mapType, mapValue, k, v) + cursor = skipWhiteSpace(buf, valueCursor) + if buf[cursor] == '}' { + **(**unsafe.Pointer)(unsafe.Pointer(&p)) = mapValue + cursor++ + return cursor, nil + } + if buf[cursor] != ',' { + return 0, errors.ErrExpected("comma after object value", cursor) + } + cursor++ + } +} + +func (d *mapDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) { + buf := ctx.Buf + depth++ + if depth > maxDecodeNestingDepth { + return nil, 0, errors.ErrExceededMaxDepth(buf[cursor], cursor) + } + + cursor = skipWhiteSpace(buf, cursor) + buflen := int64(len(buf)) + if buflen < 2 { + return nil, 0, errors.ErrExpected("{} for map", cursor) + } + switch buf[cursor] { + case 'n': + if err := validateNull(buf, cursor); err != nil { + return nil, 0, err + } + cursor += 4 + return [][]byte{nullbytes}, cursor, nil + case '{': + default: + return nil, 0, errors.ErrExpected("{ character for map value", cursor) + } + cursor++ + cursor = skipWhiteSpace(buf, cursor) + if buf[cursor] == '}' { + cursor++ + return nil, cursor, nil + } + keyDecoder, ok := d.keyDecoder.(*stringDecoder) + if !ok { + return nil, 0, &errors.UnmarshalTypeError{ + Value: "string", + Type: reflect.TypeOf(""), + Offset: cursor, + Struct: d.structName, + Field: d.fieldName, + } + } + ret := [][]byte{} + for { + key, keyCursor, err := keyDecoder.decodeByte(buf, cursor) + if err != nil { + return nil, 0, err + } + cursor = skipWhiteSpace(buf, keyCursor) + if buf[cursor] != ':' { + return nil, 0, errors.ErrExpected("colon after object key", cursor) + } + cursor++ + child, found, err := ctx.Option.Path.Field(string(key)) + if err != nil { + return nil, 0, err + } + if found { + if child != nil { + oldPath := ctx.Option.Path.node + ctx.Option.Path.node = child + paths, c, err := d.valueDecoder.DecodePath(ctx, cursor, depth) + if err != nil { + return nil, 0, err + } + ctx.Option.Path.node = oldPath + ret = append(ret, paths...) + cursor = c + } else { + start := cursor + end, err := skipValue(buf, cursor, depth) + if err != nil { + return nil, 0, err + } + ret = append(ret, buf[start:end]) + cursor = end + } + } else { + c, err := skipValue(buf, cursor, depth) + if err != nil { + return nil, 0, err + } + cursor = c + } + cursor = skipWhiteSpace(buf, cursor) + if buf[cursor] == '}' { + cursor++ + return ret, cursor, nil + } + if buf[cursor] != ',' { + return nil, 0, errors.ErrExpected("comma after object value", cursor) + } + cursor++ + } +} diff --git a/vendor/github.com/goccy/go-json/internal/decoder/number.go b/vendor/github.com/goccy/go-json/internal/decoder/number.go new file mode 100644 index 000000000..10e5435e6 --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/decoder/number.go @@ -0,0 +1,123 @@ +package decoder + +import ( + "encoding/json" + "strconv" + "unsafe" + + "github.com/goccy/go-json/internal/errors" +) + +type numberDecoder struct { + stringDecoder *stringDecoder + op func(unsafe.Pointer, json.Number) + structName string + fieldName string +} + +func newNumberDecoder(structName, fieldName string, op func(unsafe.Pointer, json.Number)) *numberDecoder { + return &numberDecoder{ + stringDecoder: newStringDecoder(structName, fieldName), + op: op, + structName: structName, + fieldName: fieldName, + } +} + +func (d *numberDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error { + bytes, err := d.decodeStreamByte(s) + if err != nil { + return err + } + if _, err := strconv.ParseFloat(*(*string)(unsafe.Pointer(&bytes)), 64); err != nil { + return errors.ErrSyntax(err.Error(), s.totalOffset()) + } + d.op(p, json.Number(string(bytes))) + s.reset() + return nil +} + +func (d *numberDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { + bytes, c, err := d.decodeByte(ctx.Buf, cursor) + if err != nil { + return 0, err + } + if _, err := strconv.ParseFloat(*(*string)(unsafe.Pointer(&bytes)), 64); err != nil { + return 0, errors.ErrSyntax(err.Error(), c) + } + cursor = c + s := *(*string)(unsafe.Pointer(&bytes)) + d.op(p, json.Number(s)) + return cursor, nil +} + +func (d *numberDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) { + bytes, c, err := d.decodeByte(ctx.Buf, cursor) + if err != nil { + return nil, 0, err + } + if bytes == nil { + return [][]byte{nullbytes}, c, nil + } + return [][]byte{bytes}, c, nil +} + +func (d *numberDecoder) decodeStreamByte(s *Stream) ([]byte, error) { + start := s.cursor + for { + switch s.char() { + case ' ', '\n', '\t', '\r': + s.cursor++ + continue + case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + return floatBytes(s), nil + case 'n': + if err := nullBytes(s); err != nil { + return nil, err + } + return nil, nil + case '"': + return d.stringDecoder.decodeStreamByte(s) + case nul: + if s.read() { + continue + } + goto ERROR + default: + goto ERROR + } + } +ERROR: + if s.cursor == start { + return nil, errors.ErrInvalidBeginningOfValue(s.char(), s.totalOffset()) + } + return nil, errors.ErrUnexpectedEndOfJSON("json.Number", s.totalOffset()) +} + +func (d *numberDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) { + for { + switch buf[cursor] { + case ' ', '\n', '\t', '\r': + cursor++ + continue + case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + start := cursor + cursor++ + for floatTable[buf[cursor]] { + cursor++ + } + num := buf[start:cursor] + return num, cursor, nil + case 'n': + if err := validateNull(buf, cursor); err != nil { + return nil, 0, err + } + cursor += 4 + return nil, cursor, nil + case '"': + return d.stringDecoder.decodeByte(buf, cursor) + default: + return nil, 0, errors.ErrUnexpectedEndOfJSON("json.Number", cursor) + } + } +} diff --git a/vendor/github.com/goccy/go-json/internal/decoder/option.go b/vendor/github.com/goccy/go-json/internal/decoder/option.go new file mode 100644 index 000000000..502f772eb --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/decoder/option.go @@ -0,0 +1,17 @@ +package decoder + +import "context" + +type OptionFlags uint8 + +const ( + FirstWinOption OptionFlags = 1 << iota + ContextOption + PathOption +) + +type Option struct { + Flags OptionFlags + Context context.Context + Path *Path +} diff --git a/vendor/github.com/goccy/go-json/internal/decoder/path.go b/vendor/github.com/goccy/go-json/internal/decoder/path.go new file mode 100644 index 000000000..a15ff69e3 --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/decoder/path.go @@ -0,0 +1,670 @@ +package decoder + +import ( + "fmt" + "reflect" + "strconv" + + "github.com/goccy/go-json/internal/errors" + "github.com/goccy/go-json/internal/runtime" +) + +type PathString string + +func (s PathString) Build() (*Path, error) { + builder := new(PathBuilder) + return builder.Build([]rune(s)) +} + +type PathBuilder struct { + root PathNode + node PathNode + singleQuotePathSelector bool + doubleQuotePathSelector bool +} + +func (b *PathBuilder) Build(buf []rune) (*Path, error) { + node, err := b.build(buf) + if err != nil { + return nil, err + } + return &Path{ + node: node, + RootSelectorOnly: node == nil, + SingleQuotePathSelector: b.singleQuotePathSelector, + DoubleQuotePathSelector: b.doubleQuotePathSelector, + }, nil +} + +func (b *PathBuilder) build(buf []rune) (PathNode, error) { + if len(buf) == 0 { + return nil, errors.ErrEmptyPath() + } + if buf[0] != '$' { + return nil, errors.ErrInvalidPath("JSON Path must start with a $ character") + } + if len(buf) == 1 { + return nil, nil + } + buf = buf[1:] + offset, err := b.buildNext(buf) + if err != nil { + return nil, err + } + if len(buf) > offset { + return nil, errors.ErrInvalidPath("remain invalid path %q", buf[offset:]) + } + return b.root, nil +} + +func (b *PathBuilder) buildNextCharIfExists(buf []rune, cursor int) (int, error) { + if len(buf) > cursor { + offset, err := b.buildNext(buf[cursor:]) + if err != nil { + return 0, err + } + return cursor + 1 + offset, nil + } + return cursor, nil +} + +func (b *PathBuilder) buildNext(buf []rune) (int, error) { + switch buf[0] { + case '.': + if len(buf) == 1 { + return 0, errors.ErrInvalidPath("JSON Path ends with dot character") + } + offset, err := b.buildSelector(buf[1:]) + if err != nil { + return 0, err + } + return offset + 1, nil + case '[': + if len(buf) == 1 { + return 0, errors.ErrInvalidPath("JSON Path ends with left bracket character") + } + offset, err := b.buildIndex(buf[1:]) + if err != nil { + return 0, err + } + return offset + 1, nil + default: + return 0, errors.ErrInvalidPath("expect dot or left bracket character. but found %c character", buf[0]) + } +} + +func (b *PathBuilder) buildSelector(buf []rune) (int, error) { + switch buf[0] { + case '.': + if len(buf) == 1 { + return 0, errors.ErrInvalidPath("JSON Path ends with double dot character") + } + offset, err := b.buildPathRecursive(buf[1:]) + if err != nil { + return 0, err + } + return 1 + offset, nil + case '[', ']', '$', '*': + return 0, errors.ErrInvalidPath("found invalid path character %c after dot", buf[0]) + } + for cursor := 0; cursor < len(buf); cursor++ { + switch buf[cursor] { + case '$', '*', ']': + return 0, errors.ErrInvalidPath("found %c character in field selector context", buf[cursor]) + case '.': + if cursor+1 >= len(buf) { + return 0, errors.ErrInvalidPath("JSON Path ends with dot character") + } + selector := buf[:cursor] + b.addSelectorNode(string(selector)) + offset, err := b.buildSelector(buf[cursor+1:]) + if err != nil { + return 0, err + } + return cursor + 1 + offset, nil + case '[': + if cursor+1 >= len(buf) { + return 0, errors.ErrInvalidPath("JSON Path ends with left bracket character") + } + selector := buf[:cursor] + b.addSelectorNode(string(selector)) + offset, err := b.buildIndex(buf[cursor+1:]) + if err != nil { + return 0, err + } + return cursor + 1 + offset, nil + case '"': + if cursor+1 >= len(buf) { + return 0, errors.ErrInvalidPath("JSON Path ends with double quote character") + } + offset, err := b.buildQuoteSelector(buf[cursor+1:], DoubleQuotePathSelector) + if err != nil { + return 0, err + } + return cursor + 1 + offset, nil + } + } + b.addSelectorNode(string(buf)) + return len(buf), nil +} + +func (b *PathBuilder) buildQuoteSelector(buf []rune, sel QuotePathSelector) (int, error) { + switch buf[0] { + case '[', ']', '$', '.', '*', '\'', '"': + return 0, errors.ErrInvalidPath("found invalid path character %c after quote", buf[0]) + } + for cursor := 0; cursor < len(buf); cursor++ { + switch buf[cursor] { + case '\'': + if sel != SingleQuotePathSelector { + return 0, errors.ErrInvalidPath("found double quote character in field selector with single quote context") + } + if len(buf) <= cursor+1 { + return 0, errors.ErrInvalidPath("JSON Path ends with single quote character in field selector context") + } + if buf[cursor+1] != ']' { + return 0, errors.ErrInvalidPath("expect right bracket for field selector with single quote but found %c", buf[cursor+1]) + } + selector := buf[:cursor] + b.addSelectorNode(string(selector)) + b.singleQuotePathSelector = true + return b.buildNextCharIfExists(buf, cursor+2) + case '"': + if sel != DoubleQuotePathSelector { + return 0, errors.ErrInvalidPath("found single quote character in field selector with double quote context") + } + selector := buf[:cursor] + b.addSelectorNode(string(selector)) + b.doubleQuotePathSelector = true + return b.buildNextCharIfExists(buf, cursor+1) + } + } + return 0, errors.ErrInvalidPath("couldn't find quote character in selector quote path context") +} + +func (b *PathBuilder) buildPathRecursive(buf []rune) (int, error) { + switch buf[0] { + case '.', '[', ']', '$', '*': + return 0, errors.ErrInvalidPath("found invalid path character %c after double dot", buf[0]) + } + for cursor := 0; cursor < len(buf); cursor++ { + switch buf[cursor] { + case '$', '*', ']': + return 0, errors.ErrInvalidPath("found %c character in field selector context", buf[cursor]) + case '.': + if cursor+1 >= len(buf) { + return 0, errors.ErrInvalidPath("JSON Path ends with dot character") + } + selector := buf[:cursor] + b.addRecursiveNode(string(selector)) + offset, err := b.buildSelector(buf[cursor+1:]) + if err != nil { + return 0, err + } + return cursor + 1 + offset, nil + case '[': + if cursor+1 >= len(buf) { + return 0, errors.ErrInvalidPath("JSON Path ends with left bracket character") + } + selector := buf[:cursor] + b.addRecursiveNode(string(selector)) + offset, err := b.buildIndex(buf[cursor+1:]) + if err != nil { + return 0, err + } + return cursor + 1 + offset, nil + } + } + b.addRecursiveNode(string(buf)) + return len(buf), nil +} + +func (b *PathBuilder) buildIndex(buf []rune) (int, error) { + switch buf[0] { + case '.', '[', ']', '$': + return 0, errors.ErrInvalidPath("found invalid path character %c after left bracket", buf[0]) + case '\'': + if len(buf) == 1 { + return 0, errors.ErrInvalidPath("JSON Path ends with single quote character") + } + offset, err := b.buildQuoteSelector(buf[1:], SingleQuotePathSelector) + if err != nil { + return 0, err + } + return 1 + offset, nil + case '*': + if len(buf) == 1 { + return 0, errors.ErrInvalidPath("JSON Path ends with star character") + } + if buf[1] != ']' { + return 0, errors.ErrInvalidPath("expect right bracket character for index all path but found %c character", buf[1]) + } + b.addIndexAllNode() + offset := len("*]") + if len(buf) > 2 { + buildOffset, err := b.buildNext(buf[2:]) + if err != nil { + return 0, err + } + return offset + buildOffset, nil + } + return offset, nil + } + + for cursor := 0; cursor < len(buf); cursor++ { + switch buf[cursor] { + case ']': + index, err := strconv.ParseInt(string(buf[:cursor]), 10, 64) + if err != nil { + return 0, errors.ErrInvalidPath("%q is unexpected index path", buf[:cursor]) + } + b.addIndexNode(int(index)) + return b.buildNextCharIfExists(buf, cursor+1) + } + } + return 0, errors.ErrInvalidPath("couldn't find right bracket character in index path context") +} + +func (b *PathBuilder) addIndexAllNode() { + node := newPathIndexAllNode() + if b.root == nil { + b.root = node + b.node = node + } else { + b.node = b.node.chain(node) + } +} + +func (b *PathBuilder) addRecursiveNode(selector string) { + node := newPathRecursiveNode(selector) + if b.root == nil { + b.root = node + b.node = node + } else { + b.node = b.node.chain(node) + } +} + +func (b *PathBuilder) addSelectorNode(name string) { + node := newPathSelectorNode(name) + if b.root == nil { + b.root = node + b.node = node + } else { + b.node = b.node.chain(node) + } +} + +func (b *PathBuilder) addIndexNode(idx int) { + node := newPathIndexNode(idx) + if b.root == nil { + b.root = node + b.node = node + } else { + b.node = b.node.chain(node) + } +} + +type QuotePathSelector int + +const ( + SingleQuotePathSelector QuotePathSelector = 1 + DoubleQuotePathSelector QuotePathSelector = 2 +) + +type Path struct { + node PathNode + RootSelectorOnly bool + SingleQuotePathSelector bool + DoubleQuotePathSelector bool +} + +func (p *Path) Field(sel string) (PathNode, bool, error) { + if p.node == nil { + return nil, false, nil + } + return p.node.Field(sel) +} + +func (p *Path) Get(src, dst reflect.Value) error { + if p.node == nil { + return nil + } + return p.node.Get(src, dst) +} + +func (p *Path) String() string { + if p.node == nil { + return "$" + } + return p.node.String() +} + +type PathNode interface { + fmt.Stringer + Index(idx int) (PathNode, bool, error) + Field(fieldName string) (PathNode, bool, error) + Get(src, dst reflect.Value) error + chain(PathNode) PathNode + target() bool + single() bool +} + +type BasePathNode struct { + child PathNode +} + +func (n *BasePathNode) chain(node PathNode) PathNode { + n.child = node + return node +} + +func (n *BasePathNode) target() bool { + return n.child == nil +} + +func (n *BasePathNode) single() bool { + return true +} + +type PathSelectorNode struct { + *BasePathNode + selector string +} + +func newPathSelectorNode(selector string) *PathSelectorNode { + return &PathSelectorNode{ + BasePathNode: &BasePathNode{}, + selector: selector, + } +} + +func (n *PathSelectorNode) Index(idx int) (PathNode, bool, error) { + return nil, false, &errors.PathError{} +} + +func (n *PathSelectorNode) Field(fieldName string) (PathNode, bool, error) { + if n.selector == fieldName { + return n.child, true, nil + } + return nil, false, nil +} + +func (n *PathSelectorNode) Get(src, dst reflect.Value) error { + switch src.Type().Kind() { + case reflect.Map: + iter := src.MapRange() + for iter.Next() { + key, ok := iter.Key().Interface().(string) + if !ok { + return fmt.Errorf("invalid map key type %T", src.Type().Key()) + } + child, found, err := n.Field(key) + if err != nil { + return err + } + if found { + if child != nil { + return child.Get(iter.Value(), dst) + } + return AssignValue(iter.Value(), dst) + } + } + case reflect.Struct: + typ := src.Type() + for i := 0; i < typ.Len(); i++ { + tag := runtime.StructTagFromField(typ.Field(i)) + child, found, err := n.Field(tag.Key) + if err != nil { + return err + } + if found { + if child != nil { + return child.Get(src.Field(i), dst) + } + return AssignValue(src.Field(i), dst) + } + } + case reflect.Ptr: + return n.Get(src.Elem(), dst) + case reflect.Interface: + return n.Get(reflect.ValueOf(src.Interface()), dst) + case reflect.Float64, reflect.String, reflect.Bool: + return AssignValue(src, dst) + } + return fmt.Errorf("failed to get %s value from %s", n.selector, src.Type()) +} + +func (n *PathSelectorNode) String() string { + s := fmt.Sprintf(".%s", n.selector) + if n.child != nil { + s += n.child.String() + } + return s +} + +type PathIndexNode struct { + *BasePathNode + selector int +} + +func newPathIndexNode(selector int) *PathIndexNode { + return &PathIndexNode{ + BasePathNode: &BasePathNode{}, + selector: selector, + } +} + +func (n *PathIndexNode) Index(idx int) (PathNode, bool, error) { + if n.selector == idx { + return n.child, true, nil + } + return nil, false, nil +} + +func (n *PathIndexNode) Field(fieldName string) (PathNode, bool, error) { + return nil, false, &errors.PathError{} +} + +func (n *PathIndexNode) Get(src, dst reflect.Value) error { + switch src.Type().Kind() { + case reflect.Array, reflect.Slice: + if src.Len() > n.selector { + if n.child != nil { + return n.child.Get(src.Index(n.selector), dst) + } + return AssignValue(src.Index(n.selector), dst) + } + case reflect.Ptr: + return n.Get(src.Elem(), dst) + case reflect.Interface: + return n.Get(reflect.ValueOf(src.Interface()), dst) + } + return fmt.Errorf("failed to get [%d] value from %s", n.selector, src.Type()) +} + +func (n *PathIndexNode) String() string { + s := fmt.Sprintf("[%d]", n.selector) + if n.child != nil { + s += n.child.String() + } + return s +} + +type PathIndexAllNode struct { + *BasePathNode +} + +func newPathIndexAllNode() *PathIndexAllNode { + return &PathIndexAllNode{ + BasePathNode: &BasePathNode{}, + } +} + +func (n *PathIndexAllNode) Index(idx int) (PathNode, bool, error) { + return n.child, true, nil +} + +func (n *PathIndexAllNode) Field(fieldName string) (PathNode, bool, error) { + return nil, false, &errors.PathError{} +} + +func (n *PathIndexAllNode) Get(src, dst reflect.Value) error { + switch src.Type().Kind() { + case reflect.Array, reflect.Slice: + var arr []interface{} + for i := 0; i < src.Len(); i++ { + var v interface{} + rv := reflect.ValueOf(&v) + if n.child != nil { + if err := n.child.Get(src.Index(i), rv); err != nil { + return err + } + } else { + if err := AssignValue(src.Index(i), rv); err != nil { + return err + } + } + arr = append(arr, v) + } + if err := AssignValue(reflect.ValueOf(arr), dst); err != nil { + return err + } + return nil + case reflect.Ptr: + return n.Get(src.Elem(), dst) + case reflect.Interface: + return n.Get(reflect.ValueOf(src.Interface()), dst) + } + return fmt.Errorf("failed to get all value from %s", src.Type()) +} + +func (n *PathIndexAllNode) String() string { + s := "[*]" + if n.child != nil { + s += n.child.String() + } + return s +} + +type PathRecursiveNode struct { + *BasePathNode + selector string +} + +func newPathRecursiveNode(selector string) *PathRecursiveNode { + node := newPathSelectorNode(selector) + return &PathRecursiveNode{ + BasePathNode: &BasePathNode{ + child: node, + }, + selector: selector, + } +} + +func (n *PathRecursiveNode) Field(fieldName string) (PathNode, bool, error) { + if n.selector == fieldName { + return n.child, true, nil + } + return nil, false, nil +} + +func (n *PathRecursiveNode) Index(_ int) (PathNode, bool, error) { + return n, true, nil +} + +func valueToSliceValue(v interface{}) []interface{} { + rv := reflect.ValueOf(v) + ret := []interface{}{} + if rv.Type().Kind() == reflect.Slice || rv.Type().Kind() == reflect.Array { + for i := 0; i < rv.Len(); i++ { + ret = append(ret, rv.Index(i).Interface()) + } + return ret + } + return []interface{}{v} +} + +func (n *PathRecursiveNode) Get(src, dst reflect.Value) error { + if n.child == nil { + return fmt.Errorf("failed to get by recursive path ..%s", n.selector) + } + var arr []interface{} + switch src.Type().Kind() { + case reflect.Map: + iter := src.MapRange() + for iter.Next() { + key, ok := iter.Key().Interface().(string) + if !ok { + return fmt.Errorf("invalid map key type %T", src.Type().Key()) + } + child, found, err := n.Field(key) + if err != nil { + return err + } + if found { + var v interface{} + rv := reflect.ValueOf(&v) + _ = child.Get(iter.Value(), rv) + arr = append(arr, valueToSliceValue(v)...) + } else { + var v interface{} + rv := reflect.ValueOf(&v) + _ = n.Get(iter.Value(), rv) + if v != nil { + arr = append(arr, valueToSliceValue(v)...) + } + } + } + _ = AssignValue(reflect.ValueOf(arr), dst) + return nil + case reflect.Struct: + typ := src.Type() + for i := 0; i < typ.Len(); i++ { + tag := runtime.StructTagFromField(typ.Field(i)) + child, found, err := n.Field(tag.Key) + if err != nil { + return err + } + if found { + var v interface{} + rv := reflect.ValueOf(&v) + _ = child.Get(src.Field(i), rv) + arr = append(arr, valueToSliceValue(v)...) + } else { + var v interface{} + rv := reflect.ValueOf(&v) + _ = n.Get(src.Field(i), rv) + if v != nil { + arr = append(arr, valueToSliceValue(v)...) + } + } + } + _ = AssignValue(reflect.ValueOf(arr), dst) + return nil + case reflect.Array, reflect.Slice: + for i := 0; i < src.Len(); i++ { + var v interface{} + rv := reflect.ValueOf(&v) + _ = n.Get(src.Index(i), rv) + if v != nil { + arr = append(arr, valueToSliceValue(v)...) + } + } + _ = AssignValue(reflect.ValueOf(arr), dst) + return nil + case reflect.Ptr: + return n.Get(src.Elem(), dst) + case reflect.Interface: + return n.Get(reflect.ValueOf(src.Interface()), dst) + } + return fmt.Errorf("failed to get %s value from %s", n.selector, src.Type()) +} + +func (n *PathRecursiveNode) String() string { + s := fmt.Sprintf("..%s", n.selector) + if n.child != nil { + s += n.child.String() + } + return s +} diff --git a/vendor/github.com/goccy/go-json/internal/decoder/ptr.go b/vendor/github.com/goccy/go-json/internal/decoder/ptr.go new file mode 100644 index 000000000..de12e105c --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/decoder/ptr.go @@ -0,0 +1,96 @@ +package decoder + +import ( + "fmt" + "unsafe" + + "github.com/goccy/go-json/internal/runtime" +) + +type ptrDecoder struct { + dec Decoder + typ *runtime.Type + structName string + fieldName string +} + +func newPtrDecoder(dec Decoder, typ *runtime.Type, structName, fieldName string) *ptrDecoder { + return &ptrDecoder{ + dec: dec, + typ: typ, + structName: structName, + fieldName: fieldName, + } +} + +func (d *ptrDecoder) contentDecoder() Decoder { + dec, ok := d.dec.(*ptrDecoder) + if !ok { + return d.dec + } + return dec.contentDecoder() +} + +//nolint:golint +//go:linkname unsafe_New reflect.unsafe_New +func unsafe_New(*runtime.Type) unsafe.Pointer + +func UnsafeNew(t *runtime.Type) unsafe.Pointer { + return unsafe_New(t) +} + +func (d *ptrDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error { + if s.skipWhiteSpace() == nul { + s.read() + } + if s.char() == 'n' { + if err := nullBytes(s); err != nil { + return err + } + *(*unsafe.Pointer)(p) = nil + return nil + } + var newptr unsafe.Pointer + if *(*unsafe.Pointer)(p) == nil { + newptr = unsafe_New(d.typ) + *(*unsafe.Pointer)(p) = newptr + } else { + newptr = *(*unsafe.Pointer)(p) + } + if err := d.dec.DecodeStream(s, depth, newptr); err != nil { + return err + } + return nil +} + +func (d *ptrDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { + buf := ctx.Buf + cursor = skipWhiteSpace(buf, cursor) + if buf[cursor] == 'n' { + if err := validateNull(buf, cursor); err != nil { + return 0, err + } + if p != nil { + *(*unsafe.Pointer)(p) = nil + } + cursor += 4 + return cursor, nil + } + var newptr unsafe.Pointer + if *(*unsafe.Pointer)(p) == nil { + newptr = unsafe_New(d.typ) + *(*unsafe.Pointer)(p) = newptr + } else { + newptr = *(*unsafe.Pointer)(p) + } + c, err := d.dec.Decode(ctx, cursor, depth, newptr) + if err != nil { + return 0, err + } + cursor = c + return cursor, nil +} + +func (d *ptrDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) { + return nil, 0, fmt.Errorf("json: ptr decoder does not support decode path") +} diff --git a/vendor/github.com/goccy/go-json/internal/decoder/slice.go b/vendor/github.com/goccy/go-json/internal/decoder/slice.go new file mode 100644 index 000000000..30a23e4b5 --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/decoder/slice.go @@ -0,0 +1,380 @@ +package decoder + +import ( + "reflect" + "sync" + "unsafe" + + "github.com/goccy/go-json/internal/errors" + "github.com/goccy/go-json/internal/runtime" +) + +var ( + sliceType = runtime.Type2RType( + reflect.TypeOf((*sliceHeader)(nil)).Elem(), + ) + nilSlice = unsafe.Pointer(&sliceHeader{}) +) + +type sliceDecoder struct { + elemType *runtime.Type + isElemPointerType bool + valueDecoder Decoder + size uintptr + arrayPool sync.Pool + structName string + fieldName string +} + +// If use reflect.SliceHeader, data type is uintptr. +// In this case, Go compiler cannot trace reference created by newArray(). +// So, define using unsafe.Pointer as data type +type sliceHeader struct { + data unsafe.Pointer + len int + cap int +} + +const ( + defaultSliceCapacity = 2 +) + +func newSliceDecoder(dec Decoder, elemType *runtime.Type, size uintptr, structName, fieldName string) *sliceDecoder { + return &sliceDecoder{ + valueDecoder: dec, + elemType: elemType, + isElemPointerType: elemType.Kind() == reflect.Ptr || elemType.Kind() == reflect.Map, + size: size, + arrayPool: sync.Pool{ + New: func() interface{} { + return &sliceHeader{ + data: newArray(elemType, defaultSliceCapacity), + len: 0, + cap: defaultSliceCapacity, + } + }, + }, + structName: structName, + fieldName: fieldName, + } +} + +func (d *sliceDecoder) newSlice(src *sliceHeader) *sliceHeader { + slice := d.arrayPool.Get().(*sliceHeader) + if src.len > 0 { + // copy original elem + if slice.cap < src.cap { + data := newArray(d.elemType, src.cap) + slice = &sliceHeader{data: data, len: src.len, cap: src.cap} + } else { + slice.len = src.len + } + copySlice(d.elemType, *slice, *src) + } else { + slice.len = 0 + } + return slice +} + +func (d *sliceDecoder) releaseSlice(p *sliceHeader) { + d.arrayPool.Put(p) +} + +//go:linkname copySlice reflect.typedslicecopy +func copySlice(elemType *runtime.Type, dst, src sliceHeader) int + +//go:linkname newArray reflect.unsafe_NewArray +func newArray(*runtime.Type, int) unsafe.Pointer + +//go:linkname typedmemmove reflect.typedmemmove +func typedmemmove(t *runtime.Type, dst, src unsafe.Pointer) + +func (d *sliceDecoder) errNumber(offset int64) *errors.UnmarshalTypeError { + return &errors.UnmarshalTypeError{ + Value: "number", + Type: reflect.SliceOf(runtime.RType2Type(d.elemType)), + Struct: d.structName, + Field: d.fieldName, + Offset: offset, + } +} + +func (d *sliceDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error { + depth++ + if depth > maxDecodeNestingDepth { + return errors.ErrExceededMaxDepth(s.char(), s.cursor) + } + + for { + switch s.char() { + case ' ', '\n', '\t', '\r': + s.cursor++ + continue + case 'n': + if err := nullBytes(s); err != nil { + return err + } + typedmemmove(sliceType, p, nilSlice) + return nil + case '[': + s.cursor++ + if s.skipWhiteSpace() == ']' { + dst := (*sliceHeader)(p) + if dst.data == nil { + dst.data = newArray(d.elemType, 0) + } else { + dst.len = 0 + } + s.cursor++ + return nil + } + idx := 0 + slice := d.newSlice((*sliceHeader)(p)) + srcLen := slice.len + capacity := slice.cap + data := slice.data + for { + if capacity <= idx { + src := sliceHeader{data: data, len: idx, cap: capacity} + capacity *= 2 + data = newArray(d.elemType, capacity) + dst := sliceHeader{data: data, len: idx, cap: capacity} + copySlice(d.elemType, dst, src) + } + ep := unsafe.Pointer(uintptr(data) + uintptr(idx)*d.size) + + // if srcLen is greater than idx, keep the original reference + if srcLen <= idx { + if d.isElemPointerType { + **(**unsafe.Pointer)(unsafe.Pointer(&ep)) = nil // initialize elem pointer + } else { + // assign new element to the slice + typedmemmove(d.elemType, ep, unsafe_New(d.elemType)) + } + } + + if err := d.valueDecoder.DecodeStream(s, depth, ep); err != nil { + return err + } + s.skipWhiteSpace() + RETRY: + switch s.char() { + case ']': + slice.cap = capacity + slice.len = idx + 1 + slice.data = data + dst := (*sliceHeader)(p) + dst.len = idx + 1 + if dst.len > dst.cap { + dst.data = newArray(d.elemType, dst.len) + dst.cap = dst.len + } + copySlice(d.elemType, *dst, *slice) + d.releaseSlice(slice) + s.cursor++ + return nil + case ',': + idx++ + case nul: + if s.read() { + goto RETRY + } + slice.cap = capacity + slice.data = data + d.releaseSlice(slice) + goto ERROR + default: + slice.cap = capacity + slice.data = data + d.releaseSlice(slice) + goto ERROR + } + s.cursor++ + } + case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + return d.errNumber(s.totalOffset()) + case nul: + if s.read() { + continue + } + goto ERROR + default: + goto ERROR + } + } +ERROR: + return errors.ErrUnexpectedEndOfJSON("slice", s.totalOffset()) +} + +func (d *sliceDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { + buf := ctx.Buf + depth++ + if depth > maxDecodeNestingDepth { + return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor) + } + + for { + switch buf[cursor] { + case ' ', '\n', '\t', '\r': + cursor++ + continue + case 'n': + if err := validateNull(buf, cursor); err != nil { + return 0, err + } + cursor += 4 + typedmemmove(sliceType, p, nilSlice) + return cursor, nil + case '[': + cursor++ + cursor = skipWhiteSpace(buf, cursor) + if buf[cursor] == ']' { + dst := (*sliceHeader)(p) + if dst.data == nil { + dst.data = newArray(d.elemType, 0) + } else { + dst.len = 0 + } + cursor++ + return cursor, nil + } + idx := 0 + slice := d.newSlice((*sliceHeader)(p)) + srcLen := slice.len + capacity := slice.cap + data := slice.data + for { + if capacity <= idx { + src := sliceHeader{data: data, len: idx, cap: capacity} + capacity *= 2 + data = newArray(d.elemType, capacity) + dst := sliceHeader{data: data, len: idx, cap: capacity} + copySlice(d.elemType, dst, src) + } + ep := unsafe.Pointer(uintptr(data) + uintptr(idx)*d.size) + // if srcLen is greater than idx, keep the original reference + if srcLen <= idx { + if d.isElemPointerType { + **(**unsafe.Pointer)(unsafe.Pointer(&ep)) = nil // initialize elem pointer + } else { + // assign new element to the slice + typedmemmove(d.elemType, ep, unsafe_New(d.elemType)) + } + } + c, err := d.valueDecoder.Decode(ctx, cursor, depth, ep) + if err != nil { + return 0, err + } + cursor = c + cursor = skipWhiteSpace(buf, cursor) + switch buf[cursor] { + case ']': + slice.cap = capacity + slice.len = idx + 1 + slice.data = data + dst := (*sliceHeader)(p) + dst.len = idx + 1 + if dst.len > dst.cap { + dst.data = newArray(d.elemType, dst.len) + dst.cap = dst.len + } + copySlice(d.elemType, *dst, *slice) + d.releaseSlice(slice) + cursor++ + return cursor, nil + case ',': + idx++ + default: + slice.cap = capacity + slice.data = data + d.releaseSlice(slice) + return 0, errors.ErrInvalidCharacter(buf[cursor], "slice", cursor) + } + cursor++ + } + case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + return 0, d.errNumber(cursor) + default: + return 0, errors.ErrUnexpectedEndOfJSON("slice", cursor) + } + } +} + +func (d *sliceDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) { + buf := ctx.Buf + depth++ + if depth > maxDecodeNestingDepth { + return nil, 0, errors.ErrExceededMaxDepth(buf[cursor], cursor) + } + + ret := [][]byte{} + for { + switch buf[cursor] { + case ' ', '\n', '\t', '\r': + cursor++ + continue + case 'n': + if err := validateNull(buf, cursor); err != nil { + return nil, 0, err + } + cursor += 4 + return [][]byte{nullbytes}, cursor, nil + case '[': + cursor++ + cursor = skipWhiteSpace(buf, cursor) + if buf[cursor] == ']' { + cursor++ + return ret, cursor, nil + } + idx := 0 + for { + child, found, err := ctx.Option.Path.node.Index(idx) + if err != nil { + return nil, 0, err + } + if found { + if child != nil { + oldPath := ctx.Option.Path.node + ctx.Option.Path.node = child + paths, c, err := d.valueDecoder.DecodePath(ctx, cursor, depth) + if err != nil { + return nil, 0, err + } + ctx.Option.Path.node = oldPath + ret = append(ret, paths...) + cursor = c + } else { + start := cursor + end, err := skipValue(buf, cursor, depth) + if err != nil { + return nil, 0, err + } + ret = append(ret, buf[start:end]) + cursor = end + } + } else { + c, err := skipValue(buf, cursor, depth) + if err != nil { + return nil, 0, err + } + cursor = c + } + cursor = skipWhiteSpace(buf, cursor) + switch buf[cursor] { + case ']': + cursor++ + return ret, cursor, nil + case ',': + idx++ + default: + return nil, 0, errors.ErrInvalidCharacter(buf[cursor], "slice", cursor) + } + cursor++ + } + case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + return nil, 0, d.errNumber(cursor) + default: + return nil, 0, errors.ErrUnexpectedEndOfJSON("slice", cursor) + } + } +} diff --git a/vendor/github.com/goccy/go-json/internal/decoder/stream.go b/vendor/github.com/goccy/go-json/internal/decoder/stream.go new file mode 100644 index 000000000..a383f7259 --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/decoder/stream.go @@ -0,0 +1,556 @@ +package decoder + +import ( + "bytes" + "encoding/json" + "io" + "strconv" + "unsafe" + + "github.com/goccy/go-json/internal/errors" +) + +const ( + initBufSize = 512 +) + +type Stream struct { + buf []byte + bufSize int64 + length int64 + r io.Reader + offset int64 + cursor int64 + filledBuffer bool + allRead bool + UseNumber bool + DisallowUnknownFields bool + Option *Option +} + +func NewStream(r io.Reader) *Stream { + return &Stream{ + r: r, + bufSize: initBufSize, + buf: make([]byte, initBufSize), + Option: &Option{}, + } +} + +func (s *Stream) TotalOffset() int64 { + return s.totalOffset() +} + +func (s *Stream) Buffered() io.Reader { + buflen := int64(len(s.buf)) + for i := s.cursor; i < buflen; i++ { + if s.buf[i] == nul { + return bytes.NewReader(s.buf[s.cursor:i]) + } + } + return bytes.NewReader(s.buf[s.cursor:]) +} + +func (s *Stream) PrepareForDecode() error { + for { + switch s.char() { + case ' ', '\t', '\r', '\n': + s.cursor++ + continue + case ',', ':': + s.cursor++ + return nil + case nul: + if s.read() { + continue + } + return io.EOF + } + break + } + return nil +} + +func (s *Stream) totalOffset() int64 { + return s.offset + s.cursor +} + +func (s *Stream) char() byte { + return s.buf[s.cursor] +} + +func (s *Stream) equalChar(c byte) bool { + cur := s.buf[s.cursor] + if cur == nul { + s.read() + cur = s.buf[s.cursor] + } + return cur == c +} + +func (s *Stream) stat() ([]byte, int64, unsafe.Pointer) { + return s.buf, s.cursor, (*sliceHeader)(unsafe.Pointer(&s.buf)).data +} + +func (s *Stream) bufptr() unsafe.Pointer { + return (*sliceHeader)(unsafe.Pointer(&s.buf)).data +} + +func (s *Stream) statForRetry() ([]byte, int64, unsafe.Pointer) { + s.cursor-- // for retry ( because caller progress cursor position in each loop ) + return s.buf, s.cursor, (*sliceHeader)(unsafe.Pointer(&s.buf)).data +} + +func (s *Stream) Reset() { + s.reset() + s.bufSize = int64(len(s.buf)) +} + +func (s *Stream) More() bool { + for { + switch s.char() { + case ' ', '\n', '\r', '\t': + s.cursor++ + continue + case '}', ']': + return false + case nul: + if s.read() { + continue + } + return false + } + break + } + return true +} + +func (s *Stream) Token() (interface{}, error) { + for { + c := s.char() + switch c { + case ' ', '\n', '\r', '\t': + s.cursor++ + case '{', '[', ']', '}': + s.cursor++ + return json.Delim(c), nil + case ',', ':': + s.cursor++ + case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + bytes := floatBytes(s) + str := *(*string)(unsafe.Pointer(&bytes)) + if s.UseNumber { + return json.Number(str), nil + } + f64, err := strconv.ParseFloat(str, 64) + if err != nil { + return nil, err + } + return f64, nil + case '"': + bytes, err := stringBytes(s) + if err != nil { + return nil, err + } + return string(bytes), nil + case 't': + if err := trueBytes(s); err != nil { + return nil, err + } + return true, nil + case 'f': + if err := falseBytes(s); err != nil { + return nil, err + } + return false, nil + case 'n': + if err := nullBytes(s); err != nil { + return nil, err + } + return nil, nil + case nul: + if s.read() { + continue + } + goto END + default: + return nil, errors.ErrInvalidCharacter(s.char(), "token", s.totalOffset()) + } + } +END: + return nil, io.EOF +} + +func (s *Stream) reset() { + s.offset += s.cursor + s.buf = s.buf[s.cursor:] + s.length -= s.cursor + s.cursor = 0 +} + +func (s *Stream) readBuf() []byte { + if s.filledBuffer { + s.bufSize *= 2 + remainBuf := s.buf + s.buf = make([]byte, s.bufSize) + copy(s.buf, remainBuf) + } + remainLen := s.length - s.cursor + remainNotNulCharNum := int64(0) + for i := int64(0); i < remainLen; i++ { + if s.buf[s.cursor+i] == nul { + break + } + remainNotNulCharNum++ + } + s.length = s.cursor + remainNotNulCharNum + return s.buf[s.cursor+remainNotNulCharNum:] +} + +func (s *Stream) read() bool { + if s.allRead { + return false + } + buf := s.readBuf() + last := len(buf) - 1 + buf[last] = nul + n, err := s.r.Read(buf[:last]) + s.length += int64(n) + if n == last { + s.filledBuffer = true + } else { + s.filledBuffer = false + } + if err == io.EOF { + s.allRead = true + } else if err != nil { + return false + } + return true +} + +func (s *Stream) skipWhiteSpace() byte { + p := s.bufptr() +LOOP: + c := char(p, s.cursor) + switch c { + case ' ', '\n', '\t', '\r': + s.cursor++ + goto LOOP + case nul: + if s.read() { + p = s.bufptr() + goto LOOP + } + } + return c +} + +func (s *Stream) skipObject(depth int64) error { + braceCount := 1 + _, cursor, p := s.stat() + for { + switch char(p, cursor) { + case '{': + braceCount++ + depth++ + if depth > maxDecodeNestingDepth { + return errors.ErrExceededMaxDepth(s.char(), s.cursor) + } + case '}': + braceCount-- + depth-- + if braceCount == 0 { + s.cursor = cursor + 1 + return nil + } + case '[': + depth++ + if depth > maxDecodeNestingDepth { + return errors.ErrExceededMaxDepth(s.char(), s.cursor) + } + case ']': + depth-- + case '"': + for { + cursor++ + switch char(p, cursor) { + case '\\': + cursor++ + if char(p, cursor) == nul { + s.cursor = cursor + if s.read() { + _, cursor, p = s.stat() + continue + } + return errors.ErrUnexpectedEndOfJSON("string of object", cursor) + } + case '"': + goto SWITCH_OUT + case nul: + s.cursor = cursor + if s.read() { + _, cursor, p = s.statForRetry() + continue + } + return errors.ErrUnexpectedEndOfJSON("string of object", cursor) + } + } + case nul: + s.cursor = cursor + if s.read() { + _, cursor, p = s.stat() + continue + } + return errors.ErrUnexpectedEndOfJSON("object of object", cursor) + } + SWITCH_OUT: + cursor++ + } +} + +func (s *Stream) skipArray(depth int64) error { + bracketCount := 1 + _, cursor, p := s.stat() + for { + switch char(p, cursor) { + case '[': + bracketCount++ + depth++ + if depth > maxDecodeNestingDepth { + return errors.ErrExceededMaxDepth(s.char(), s.cursor) + } + case ']': + bracketCount-- + depth-- + if bracketCount == 0 { + s.cursor = cursor + 1 + return nil + } + case '{': + depth++ + if depth > maxDecodeNestingDepth { + return errors.ErrExceededMaxDepth(s.char(), s.cursor) + } + case '}': + depth-- + case '"': + for { + cursor++ + switch char(p, cursor) { + case '\\': + cursor++ + if char(p, cursor) == nul { + s.cursor = cursor + if s.read() { + _, cursor, p = s.stat() + continue + } + return errors.ErrUnexpectedEndOfJSON("string of object", cursor) + } + case '"': + goto SWITCH_OUT + case nul: + s.cursor = cursor + if s.read() { + _, cursor, p = s.statForRetry() + continue + } + return errors.ErrUnexpectedEndOfJSON("string of object", cursor) + } + } + case nul: + s.cursor = cursor + if s.read() { + _, cursor, p = s.stat() + continue + } + return errors.ErrUnexpectedEndOfJSON("array of object", cursor) + } + SWITCH_OUT: + cursor++ + } +} + +func (s *Stream) skipValue(depth int64) error { + _, cursor, p := s.stat() + for { + switch char(p, cursor) { + case ' ', '\n', '\t', '\r': + cursor++ + continue + case nul: + s.cursor = cursor + if s.read() { + _, cursor, p = s.stat() + continue + } + return errors.ErrUnexpectedEndOfJSON("value of object", s.totalOffset()) + case '{': + s.cursor = cursor + 1 + return s.skipObject(depth + 1) + case '[': + s.cursor = cursor + 1 + return s.skipArray(depth + 1) + case '"': + for { + cursor++ + switch char(p, cursor) { + case '\\': + cursor++ + if char(p, cursor) == nul { + s.cursor = cursor + if s.read() { + _, cursor, p = s.stat() + continue + } + return errors.ErrUnexpectedEndOfJSON("value of string", s.totalOffset()) + } + case '"': + s.cursor = cursor + 1 + return nil + case nul: + s.cursor = cursor + if s.read() { + _, cursor, p = s.statForRetry() + continue + } + return errors.ErrUnexpectedEndOfJSON("value of string", s.totalOffset()) + } + } + case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + for { + cursor++ + c := char(p, cursor) + if floatTable[c] { + continue + } else if c == nul { + if s.read() { + _, cursor, p = s.stat() + continue + } + } + s.cursor = cursor + return nil + } + case 't': + s.cursor = cursor + if err := trueBytes(s); err != nil { + return err + } + return nil + case 'f': + s.cursor = cursor + if err := falseBytes(s); err != nil { + return err + } + return nil + case 'n': + s.cursor = cursor + if err := nullBytes(s); err != nil { + return err + } + return nil + } + cursor++ + } +} + +func nullBytes(s *Stream) error { + // current cursor's character is 'n' + s.cursor++ + if s.char() != 'u' { + if err := retryReadNull(s); err != nil { + return err + } + } + s.cursor++ + if s.char() != 'l' { + if err := retryReadNull(s); err != nil { + return err + } + } + s.cursor++ + if s.char() != 'l' { + if err := retryReadNull(s); err != nil { + return err + } + } + s.cursor++ + return nil +} + +func retryReadNull(s *Stream) error { + if s.char() == nul && s.read() { + return nil + } + return errors.ErrInvalidCharacter(s.char(), "null", s.totalOffset()) +} + +func trueBytes(s *Stream) error { + // current cursor's character is 't' + s.cursor++ + if s.char() != 'r' { + if err := retryReadTrue(s); err != nil { + return err + } + } + s.cursor++ + if s.char() != 'u' { + if err := retryReadTrue(s); err != nil { + return err + } + } + s.cursor++ + if s.char() != 'e' { + if err := retryReadTrue(s); err != nil { + return err + } + } + s.cursor++ + return nil +} + +func retryReadTrue(s *Stream) error { + if s.char() == nul && s.read() { + return nil + } + return errors.ErrInvalidCharacter(s.char(), "bool(true)", s.totalOffset()) +} + +func falseBytes(s *Stream) error { + // current cursor's character is 'f' + s.cursor++ + if s.char() != 'a' { + if err := retryReadFalse(s); err != nil { + return err + } + } + s.cursor++ + if s.char() != 'l' { + if err := retryReadFalse(s); err != nil { + return err + } + } + s.cursor++ + if s.char() != 's' { + if err := retryReadFalse(s); err != nil { + return err + } + } + s.cursor++ + if s.char() != 'e' { + if err := retryReadFalse(s); err != nil { + return err + } + } + s.cursor++ + return nil +} + +func retryReadFalse(s *Stream) error { + if s.char() == nul && s.read() { + return nil + } + return errors.ErrInvalidCharacter(s.char(), "bool(false)", s.totalOffset()) +} diff --git a/vendor/github.com/goccy/go-json/internal/decoder/string.go b/vendor/github.com/goccy/go-json/internal/decoder/string.go new file mode 100644 index 000000000..32602c908 --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/decoder/string.go @@ -0,0 +1,452 @@ +package decoder + +import ( + "bytes" + "fmt" + "reflect" + "unicode" + "unicode/utf16" + "unicode/utf8" + "unsafe" + + "github.com/goccy/go-json/internal/errors" +) + +type stringDecoder struct { + structName string + fieldName string +} + +func newStringDecoder(structName, fieldName string) *stringDecoder { + return &stringDecoder{ + structName: structName, + fieldName: fieldName, + } +} + +func (d *stringDecoder) errUnmarshalType(typeName string, offset int64) *errors.UnmarshalTypeError { + return &errors.UnmarshalTypeError{ + Value: typeName, + Type: reflect.TypeOf(""), + Offset: offset, + Struct: d.structName, + Field: d.fieldName, + } +} + +func (d *stringDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error { + bytes, err := d.decodeStreamByte(s) + if err != nil { + return err + } + if bytes == nil { + return nil + } + **(**string)(unsafe.Pointer(&p)) = *(*string)(unsafe.Pointer(&bytes)) + s.reset() + return nil +} + +func (d *stringDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { + bytes, c, err := d.decodeByte(ctx.Buf, cursor) + if err != nil { + return 0, err + } + if bytes == nil { + return c, nil + } + cursor = c + **(**string)(unsafe.Pointer(&p)) = *(*string)(unsafe.Pointer(&bytes)) + return cursor, nil +} + +func (d *stringDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) { + bytes, c, err := d.decodeByte(ctx.Buf, cursor) + if err != nil { + return nil, 0, err + } + if bytes == nil { + return [][]byte{nullbytes}, c, nil + } + return [][]byte{bytes}, c, nil +} + +var ( + hexToInt = [256]int{ + '0': 0, + '1': 1, + '2': 2, + '3': 3, + '4': 4, + '5': 5, + '6': 6, + '7': 7, + '8': 8, + '9': 9, + 'A': 10, + 'B': 11, + 'C': 12, + 'D': 13, + 'E': 14, + 'F': 15, + 'a': 10, + 'b': 11, + 'c': 12, + 'd': 13, + 'e': 14, + 'f': 15, + } +) + +func unicodeToRune(code []byte) rune { + var r rune + for i := 0; i < len(code); i++ { + r = r*16 + rune(hexToInt[code[i]]) + } + return r +} + +func readAtLeast(s *Stream, n int64, p *unsafe.Pointer) bool { + for s.cursor+n >= s.length { + if !s.read() { + return false + } + *p = s.bufptr() + } + return true +} + +func decodeUnicodeRune(s *Stream, p unsafe.Pointer) (rune, int64, unsafe.Pointer, error) { + const defaultOffset = 5 + const surrogateOffset = 11 + + if !readAtLeast(s, defaultOffset, &p) { + return rune(0), 0, nil, errors.ErrInvalidCharacter(s.char(), "escaped string", s.totalOffset()) + } + + r := unicodeToRune(s.buf[s.cursor+1 : s.cursor+defaultOffset]) + if utf16.IsSurrogate(r) { + if !readAtLeast(s, surrogateOffset, &p) { + return unicode.ReplacementChar, defaultOffset, p, nil + } + if s.buf[s.cursor+defaultOffset] != '\\' || s.buf[s.cursor+defaultOffset+1] != 'u' { + return unicode.ReplacementChar, defaultOffset, p, nil + } + r2 := unicodeToRune(s.buf[s.cursor+defaultOffset+2 : s.cursor+surrogateOffset]) + if r := utf16.DecodeRune(r, r2); r != unicode.ReplacementChar { + return r, surrogateOffset, p, nil + } + } + return r, defaultOffset, p, nil +} + +func decodeUnicode(s *Stream, p unsafe.Pointer) (unsafe.Pointer, error) { + const backSlashAndULen = 2 // length of \u + + r, offset, pp, err := decodeUnicodeRune(s, p) + if err != nil { + return nil, err + } + unicode := []byte(string(r)) + unicodeLen := int64(len(unicode)) + s.buf = append(append(s.buf[:s.cursor-1], unicode...), s.buf[s.cursor+offset:]...) + unicodeOrgLen := offset - 1 + s.length = s.length - (backSlashAndULen + (unicodeOrgLen - unicodeLen)) + s.cursor = s.cursor - backSlashAndULen + unicodeLen + return pp, nil +} + +func decodeEscapeString(s *Stream, p unsafe.Pointer) (unsafe.Pointer, error) { + s.cursor++ +RETRY: + switch s.buf[s.cursor] { + case '"': + s.buf[s.cursor] = '"' + case '\\': + s.buf[s.cursor] = '\\' + case '/': + s.buf[s.cursor] = '/' + case 'b': + s.buf[s.cursor] = '\b' + case 'f': + s.buf[s.cursor] = '\f' + case 'n': + s.buf[s.cursor] = '\n' + case 'r': + s.buf[s.cursor] = '\r' + case 't': + s.buf[s.cursor] = '\t' + case 'u': + return decodeUnicode(s, p) + case nul: + if !s.read() { + return nil, errors.ErrInvalidCharacter(s.char(), "escaped string", s.totalOffset()) + } + p = s.bufptr() + goto RETRY + default: + return nil, errors.ErrUnexpectedEndOfJSON("string", s.totalOffset()) + } + s.buf = append(s.buf[:s.cursor-1], s.buf[s.cursor:]...) + s.length-- + s.cursor-- + p = s.bufptr() + return p, nil +} + +var ( + runeErrBytes = []byte(string(utf8.RuneError)) + runeErrBytesLen = int64(len(runeErrBytes)) +) + +func stringBytes(s *Stream) ([]byte, error) { + _, cursor, p := s.stat() + cursor++ // skip double quote char + start := cursor + for { + switch char(p, cursor) { + case '\\': + s.cursor = cursor + pp, err := decodeEscapeString(s, p) + if err != nil { + return nil, err + } + p = pp + cursor = s.cursor + case '"': + literal := s.buf[start:cursor] + cursor++ + s.cursor = cursor + return literal, nil + case + // 0x00 is nul, 0x5c is '\\', 0x22 is '"' . + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, // 0x00-0x0F + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, // 0x10-0x1F + 0x20, 0x21 /*0x22,*/, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, // 0x20-0x2F + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, // 0x30-0x3F + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, // 0x40-0x4F + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B /*0x5C,*/, 0x5D, 0x5E, 0x5F, // 0x50-0x5F + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, // 0x60-0x6F + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F: // 0x70-0x7F + // character is ASCII. skip to next char + case + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, // 0x80-0x8F + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, // 0x90-0x9F + 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, // 0xA0-0xAF + 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, // 0xB0-0xBF + 0xC0, 0xC1, // 0xC0-0xC1 + 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF: // 0xF5-0xFE + // character is invalid + s.buf = append(append(append([]byte{}, s.buf[:cursor]...), runeErrBytes...), s.buf[cursor+1:]...) + _, _, p = s.stat() + cursor += runeErrBytesLen + s.length += runeErrBytesLen + continue + case nul: + s.cursor = cursor + if s.read() { + _, cursor, p = s.stat() + continue + } + goto ERROR + case 0xEF: + // RuneError is {0xEF, 0xBF, 0xBD} + if s.buf[cursor+1] == 0xBF && s.buf[cursor+2] == 0xBD { + // found RuneError: skip + cursor += 2 + break + } + fallthrough + default: + // multi bytes character + if !utf8.FullRune(s.buf[cursor : len(s.buf)-1]) { + s.cursor = cursor + if s.read() { + _, cursor, p = s.stat() + continue + } + goto ERROR + } + r, size := utf8.DecodeRune(s.buf[cursor:]) + if r == utf8.RuneError { + s.buf = append(append(append([]byte{}, s.buf[:cursor]...), runeErrBytes...), s.buf[cursor+1:]...) + cursor += runeErrBytesLen + s.length += runeErrBytesLen + _, _, p = s.stat() + } else { + cursor += int64(size) + } + continue + } + cursor++ + } +ERROR: + return nil, errors.ErrUnexpectedEndOfJSON("string", s.totalOffset()) +} + +func (d *stringDecoder) decodeStreamByte(s *Stream) ([]byte, error) { + for { + switch s.char() { + case ' ', '\n', '\t', '\r': + s.cursor++ + continue + case '[': + return nil, d.errUnmarshalType("array", s.totalOffset()) + case '{': + return nil, d.errUnmarshalType("object", s.totalOffset()) + case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + return nil, d.errUnmarshalType("number", s.totalOffset()) + case '"': + return stringBytes(s) + case 'n': + if err := nullBytes(s); err != nil { + return nil, err + } + return nil, nil + case nul: + if s.read() { + continue + } + } + break + } + return nil, errors.ErrInvalidBeginningOfValue(s.char(), s.totalOffset()) +} + +func (d *stringDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) { + for { + switch buf[cursor] { + case ' ', '\n', '\t', '\r': + cursor++ + case '[': + return nil, 0, d.errUnmarshalType("array", cursor) + case '{': + return nil, 0, d.errUnmarshalType("object", cursor) + case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + return nil, 0, d.errUnmarshalType("number", cursor) + case '"': + cursor++ + start := cursor + b := (*sliceHeader)(unsafe.Pointer(&buf)).data + escaped := 0 + for { + switch char(b, cursor) { + case '\\': + escaped++ + cursor++ + switch char(b, cursor) { + case '"', '\\', '/', 'b', 'f', 'n', 'r', 't': + cursor++ + case 'u': + buflen := int64(len(buf)) + if cursor+5 >= buflen { + return nil, 0, errors.ErrUnexpectedEndOfJSON("escaped string", cursor) + } + for i := int64(1); i <= 4; i++ { + c := char(b, cursor+i) + if !(('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F')) { + return nil, 0, errors.ErrSyntax(fmt.Sprintf("json: invalid character %c in \\u hexadecimal character escape", c), cursor+i) + } + } + cursor += 5 + default: + return nil, 0, errors.ErrUnexpectedEndOfJSON("escaped string", cursor) + } + continue + case '"': + literal := buf[start:cursor] + if escaped > 0 { + literal = literal[:unescapeString(literal)] + } + cursor++ + return literal, cursor, nil + case nul: + return nil, 0, errors.ErrUnexpectedEndOfJSON("string", cursor) + } + cursor++ + } + case 'n': + if err := validateNull(buf, cursor); err != nil { + return nil, 0, err + } + cursor += 4 + return nil, cursor, nil + default: + return nil, 0, errors.ErrInvalidBeginningOfValue(buf[cursor], cursor) + } + } +} + +var unescapeMap = [256]byte{ + '"': '"', + '\\': '\\', + '/': '/', + 'b': '\b', + 'f': '\f', + 'n': '\n', + 'r': '\r', + 't': '\t', +} + +func unsafeAdd(ptr unsafe.Pointer, offset int) unsafe.Pointer { + return unsafe.Pointer(uintptr(ptr) + uintptr(offset)) +} + +func unescapeString(buf []byte) int { + p := (*sliceHeader)(unsafe.Pointer(&buf)).data + end := unsafeAdd(p, len(buf)) + src := unsafeAdd(p, bytes.IndexByte(buf, '\\')) + dst := src + for src != end { + c := char(src, 0) + if c == '\\' { + escapeChar := char(src, 1) + if escapeChar != 'u' { + *(*byte)(dst) = unescapeMap[escapeChar] + src = unsafeAdd(src, 2) + dst = unsafeAdd(dst, 1) + } else { + v1 := hexToInt[char(src, 2)] + v2 := hexToInt[char(src, 3)] + v3 := hexToInt[char(src, 4)] + v4 := hexToInt[char(src, 5)] + code := rune((v1 << 12) | (v2 << 8) | (v3 << 4) | v4) + if code >= 0xd800 && code < 0xdc00 && uintptr(unsafeAdd(src, 11)) < uintptr(end) { + if char(src, 6) == '\\' && char(src, 7) == 'u' { + v1 := hexToInt[char(src, 8)] + v2 := hexToInt[char(src, 9)] + v3 := hexToInt[char(src, 10)] + v4 := hexToInt[char(src, 11)] + lo := rune((v1 << 12) | (v2 << 8) | (v3 << 4) | v4) + if lo >= 0xdc00 && lo < 0xe000 { + code = (code-0xd800)<<10 | (lo - 0xdc00) + 0x10000 + src = unsafeAdd(src, 6) + } + } + } + var b [utf8.UTFMax]byte + n := utf8.EncodeRune(b[:], code) + switch n { + case 4: + *(*byte)(unsafeAdd(dst, 3)) = b[3] + fallthrough + case 3: + *(*byte)(unsafeAdd(dst, 2)) = b[2] + fallthrough + case 2: + *(*byte)(unsafeAdd(dst, 1)) = b[1] + fallthrough + case 1: + *(*byte)(unsafeAdd(dst, 0)) = b[0] + } + src = unsafeAdd(src, 6) + dst = unsafeAdd(dst, n) + } + } else { + *(*byte)(dst) = c + src = unsafeAdd(src, 1) + dst = unsafeAdd(dst, 1) + } + } + return int(uintptr(dst) - uintptr(p)) +} diff --git a/vendor/github.com/goccy/go-json/internal/decoder/struct.go b/vendor/github.com/goccy/go-json/internal/decoder/struct.go new file mode 100644 index 000000000..313da153b --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/decoder/struct.go @@ -0,0 +1,845 @@ +package decoder + +import ( + "fmt" + "math" + "math/bits" + "sort" + "strings" + "unicode" + "unicode/utf16" + "unsafe" + + "github.com/goccy/go-json/internal/errors" +) + +type structFieldSet struct { + dec Decoder + offset uintptr + isTaggedKey bool + fieldIdx int + key string + keyLen int64 + err error +} + +type structDecoder struct { + fieldMap map[string]*structFieldSet + fieldUniqueNameNum int + stringDecoder *stringDecoder + structName string + fieldName string + isTriedOptimize bool + keyBitmapUint8 [][256]uint8 + keyBitmapUint16 [][256]uint16 + sortedFieldSets []*structFieldSet + keyDecoder func(*structDecoder, []byte, int64) (int64, *structFieldSet, error) + keyStreamDecoder func(*structDecoder, *Stream) (*structFieldSet, string, error) +} + +var ( + largeToSmallTable [256]byte +) + +func init() { + for i := 0; i < 256; i++ { + c := i + if 'A' <= c && c <= 'Z' { + c += 'a' - 'A' + } + largeToSmallTable[i] = byte(c) + } +} + +func toASCIILower(s string) string { + b := []byte(s) + for i := range b { + b[i] = largeToSmallTable[b[i]] + } + return string(b) +} + +func newStructDecoder(structName, fieldName string, fieldMap map[string]*structFieldSet) *structDecoder { + return &structDecoder{ + fieldMap: fieldMap, + stringDecoder: newStringDecoder(structName, fieldName), + structName: structName, + fieldName: fieldName, + keyDecoder: decodeKey, + keyStreamDecoder: decodeKeyStream, + } +} + +const ( + allowOptimizeMaxKeyLen = 64 + allowOptimizeMaxFieldLen = 16 +) + +func (d *structDecoder) tryOptimize() { + fieldUniqueNameMap := map[string]int{} + fieldIdx := -1 + for k, v := range d.fieldMap { + lower := strings.ToLower(k) + idx, exists := fieldUniqueNameMap[lower] + if exists { + v.fieldIdx = idx + } else { + fieldIdx++ + v.fieldIdx = fieldIdx + } + fieldUniqueNameMap[lower] = fieldIdx + } + d.fieldUniqueNameNum = len(fieldUniqueNameMap) + + if d.isTriedOptimize { + return + } + fieldMap := map[string]*structFieldSet{} + conflicted := map[string]struct{}{} + for k, v := range d.fieldMap { + key := strings.ToLower(k) + if key != k { + if key != toASCIILower(k) { + d.isTriedOptimize = true + return + } + // already exists same key (e.g. Hello and HELLO has same lower case key + if _, exists := conflicted[key]; exists { + d.isTriedOptimize = true + return + } + conflicted[key] = struct{}{} + } + if field, exists := fieldMap[key]; exists { + if field != v { + d.isTriedOptimize = true + return + } + } + fieldMap[key] = v + } + + if len(fieldMap) > allowOptimizeMaxFieldLen { + d.isTriedOptimize = true + return + } + + var maxKeyLen int + sortedKeys := []string{} + for key := range fieldMap { + keyLen := len(key) + if keyLen > allowOptimizeMaxKeyLen { + d.isTriedOptimize = true + return + } + if maxKeyLen < keyLen { + maxKeyLen = keyLen + } + sortedKeys = append(sortedKeys, key) + } + sort.Strings(sortedKeys) + + // By allocating one extra capacity than `maxKeyLen`, + // it is possible to avoid the process of comparing the index of the key with the length of the bitmap each time. + bitmapLen := maxKeyLen + 1 + if len(sortedKeys) <= 8 { + keyBitmap := make([][256]uint8, bitmapLen) + for i, key := range sortedKeys { + for j := 0; j < len(key); j++ { + c := key[j] + keyBitmap[j][c] |= (1 << uint(i)) + } + d.sortedFieldSets = append(d.sortedFieldSets, fieldMap[key]) + } + d.keyBitmapUint8 = keyBitmap + d.keyDecoder = decodeKeyByBitmapUint8 + d.keyStreamDecoder = decodeKeyByBitmapUint8Stream + } else { + keyBitmap := make([][256]uint16, bitmapLen) + for i, key := range sortedKeys { + for j := 0; j < len(key); j++ { + c := key[j] + keyBitmap[j][c] |= (1 << uint(i)) + } + d.sortedFieldSets = append(d.sortedFieldSets, fieldMap[key]) + } + d.keyBitmapUint16 = keyBitmap + d.keyDecoder = decodeKeyByBitmapUint16 + d.keyStreamDecoder = decodeKeyByBitmapUint16Stream + } +} + +// decode from '\uXXXX' +func decodeKeyCharByUnicodeRune(buf []byte, cursor int64) ([]byte, int64, error) { + const defaultOffset = 4 + const surrogateOffset = 6 + + if cursor+defaultOffset >= int64(len(buf)) { + return nil, 0, errors.ErrUnexpectedEndOfJSON("escaped string", cursor) + } + + r := unicodeToRune(buf[cursor : cursor+defaultOffset]) + if utf16.IsSurrogate(r) { + cursor += defaultOffset + if cursor+surrogateOffset >= int64(len(buf)) || buf[cursor] != '\\' || buf[cursor+1] != 'u' { + return []byte(string(unicode.ReplacementChar)), cursor + defaultOffset - 1, nil + } + cursor += 2 + r2 := unicodeToRune(buf[cursor : cursor+defaultOffset]) + if r := utf16.DecodeRune(r, r2); r != unicode.ReplacementChar { + return []byte(string(r)), cursor + defaultOffset - 1, nil + } + } + return []byte(string(r)), cursor + defaultOffset - 1, nil +} + +func decodeKeyCharByEscapedChar(buf []byte, cursor int64) ([]byte, int64, error) { + c := buf[cursor] + cursor++ + switch c { + case '"': + return []byte{'"'}, cursor, nil + case '\\': + return []byte{'\\'}, cursor, nil + case '/': + return []byte{'/'}, cursor, nil + case 'b': + return []byte{'\b'}, cursor, nil + case 'f': + return []byte{'\f'}, cursor, nil + case 'n': + return []byte{'\n'}, cursor, nil + case 'r': + return []byte{'\r'}, cursor, nil + case 't': + return []byte{'\t'}, cursor, nil + case 'u': + return decodeKeyCharByUnicodeRune(buf, cursor) + } + return nil, cursor, nil +} + +func decodeKeyByBitmapUint8(d *structDecoder, buf []byte, cursor int64) (int64, *structFieldSet, error) { + var ( + curBit uint8 = math.MaxUint8 + ) + b := (*sliceHeader)(unsafe.Pointer(&buf)).data + for { + switch char(b, cursor) { + case ' ', '\n', '\t', '\r': + cursor++ + case '"': + cursor++ + c := char(b, cursor) + switch c { + case '"': + cursor++ + return cursor, nil, nil + case nul: + return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor) + } + keyIdx := 0 + bitmap := d.keyBitmapUint8 + start := cursor + for { + c := char(b, cursor) + switch c { + case '"': + fieldSetIndex := bits.TrailingZeros8(curBit) + field := d.sortedFieldSets[fieldSetIndex] + keyLen := cursor - start + cursor++ + if keyLen < field.keyLen { + // early match + return cursor, nil, nil + } + return cursor, field, nil + case nul: + return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor) + case '\\': + cursor++ + chars, nextCursor, err := decodeKeyCharByEscapedChar(buf, cursor) + if err != nil { + return 0, nil, err + } + for _, c := range chars { + curBit &= bitmap[keyIdx][largeToSmallTable[c]] + if curBit == 0 { + return decodeKeyNotFound(b, cursor) + } + keyIdx++ + } + cursor = nextCursor + default: + curBit &= bitmap[keyIdx][largeToSmallTable[c]] + if curBit == 0 { + return decodeKeyNotFound(b, cursor) + } + keyIdx++ + } + cursor++ + } + default: + return cursor, nil, errors.ErrInvalidBeginningOfValue(char(b, cursor), cursor) + } + } +} + +func decodeKeyByBitmapUint16(d *structDecoder, buf []byte, cursor int64) (int64, *structFieldSet, error) { + var ( + curBit uint16 = math.MaxUint16 + ) + b := (*sliceHeader)(unsafe.Pointer(&buf)).data + for { + switch char(b, cursor) { + case ' ', '\n', '\t', '\r': + cursor++ + case '"': + cursor++ + c := char(b, cursor) + switch c { + case '"': + cursor++ + return cursor, nil, nil + case nul: + return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor) + } + keyIdx := 0 + bitmap := d.keyBitmapUint16 + start := cursor + for { + c := char(b, cursor) + switch c { + case '"': + fieldSetIndex := bits.TrailingZeros16(curBit) + field := d.sortedFieldSets[fieldSetIndex] + keyLen := cursor - start + cursor++ + if keyLen < field.keyLen { + // early match + return cursor, nil, nil + } + return cursor, field, nil + case nul: + return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor) + case '\\': + cursor++ + chars, nextCursor, err := decodeKeyCharByEscapedChar(buf, cursor) + if err != nil { + return 0, nil, err + } + for _, c := range chars { + curBit &= bitmap[keyIdx][largeToSmallTable[c]] + if curBit == 0 { + return decodeKeyNotFound(b, cursor) + } + keyIdx++ + } + cursor = nextCursor + default: + curBit &= bitmap[keyIdx][largeToSmallTable[c]] + if curBit == 0 { + return decodeKeyNotFound(b, cursor) + } + keyIdx++ + } + cursor++ + } + default: + return cursor, nil, errors.ErrInvalidBeginningOfValue(char(b, cursor), cursor) + } + } +} + +func decodeKeyNotFound(b unsafe.Pointer, cursor int64) (int64, *structFieldSet, error) { + for { + cursor++ + switch char(b, cursor) { + case '"': + cursor++ + return cursor, nil, nil + case '\\': + cursor++ + if char(b, cursor) == nul { + return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor) + } + case nul: + return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor) + } + } +} + +func decodeKey(d *structDecoder, buf []byte, cursor int64) (int64, *structFieldSet, error) { + key, c, err := d.stringDecoder.decodeByte(buf, cursor) + if err != nil { + return 0, nil, err + } + cursor = c + k := *(*string)(unsafe.Pointer(&key)) + field, exists := d.fieldMap[k] + if !exists { + return cursor, nil, nil + } + return cursor, field, nil +} + +func decodeKeyByBitmapUint8Stream(d *structDecoder, s *Stream) (*structFieldSet, string, error) { + var ( + curBit uint8 = math.MaxUint8 + ) + _, cursor, p := s.stat() + for { + switch char(p, cursor) { + case ' ', '\n', '\t', '\r': + cursor++ + case nul: + s.cursor = cursor + if s.read() { + _, cursor, p = s.stat() + continue + } + return nil, "", errors.ErrInvalidBeginningOfValue(char(p, cursor), s.totalOffset()) + case '"': + cursor++ + FIRST_CHAR: + start := cursor + switch char(p, cursor) { + case '"': + cursor++ + s.cursor = cursor + return nil, "", nil + case nul: + s.cursor = cursor + if s.read() { + _, cursor, p = s.stat() + goto FIRST_CHAR + } + return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset()) + } + keyIdx := 0 + bitmap := d.keyBitmapUint8 + for { + c := char(p, cursor) + switch c { + case '"': + fieldSetIndex := bits.TrailingZeros8(curBit) + field := d.sortedFieldSets[fieldSetIndex] + keyLen := cursor - start + cursor++ + s.cursor = cursor + if keyLen < field.keyLen { + // early match + return nil, field.key, nil + } + return field, field.key, nil + case nul: + s.cursor = cursor + if s.read() { + _, cursor, p = s.stat() + continue + } + return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset()) + case '\\': + s.cursor = cursor + 1 // skip '\' char + chars, err := decodeKeyCharByEscapeCharStream(s) + if err != nil { + return nil, "", err + } + cursor = s.cursor + for _, c := range chars { + curBit &= bitmap[keyIdx][largeToSmallTable[c]] + if curBit == 0 { + s.cursor = cursor + return decodeKeyNotFoundStream(s, start) + } + keyIdx++ + } + default: + curBit &= bitmap[keyIdx][largeToSmallTable[c]] + if curBit == 0 { + s.cursor = cursor + return decodeKeyNotFoundStream(s, start) + } + keyIdx++ + } + cursor++ + } + default: + return nil, "", errors.ErrInvalidBeginningOfValue(char(p, cursor), s.totalOffset()) + } + } +} + +func decodeKeyByBitmapUint16Stream(d *structDecoder, s *Stream) (*structFieldSet, string, error) { + var ( + curBit uint16 = math.MaxUint16 + ) + _, cursor, p := s.stat() + for { + switch char(p, cursor) { + case ' ', '\n', '\t', '\r': + cursor++ + case nul: + s.cursor = cursor + if s.read() { + _, cursor, p = s.stat() + continue + } + return nil, "", errors.ErrInvalidBeginningOfValue(char(p, cursor), s.totalOffset()) + case '"': + cursor++ + FIRST_CHAR: + start := cursor + switch char(p, cursor) { + case '"': + cursor++ + s.cursor = cursor + return nil, "", nil + case nul: + s.cursor = cursor + if s.read() { + _, cursor, p = s.stat() + goto FIRST_CHAR + } + return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset()) + } + keyIdx := 0 + bitmap := d.keyBitmapUint16 + for { + c := char(p, cursor) + switch c { + case '"': + fieldSetIndex := bits.TrailingZeros16(curBit) + field := d.sortedFieldSets[fieldSetIndex] + keyLen := cursor - start + cursor++ + s.cursor = cursor + if keyLen < field.keyLen { + // early match + return nil, field.key, nil + } + return field, field.key, nil + case nul: + s.cursor = cursor + if s.read() { + _, cursor, p = s.stat() + continue + } + return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset()) + case '\\': + s.cursor = cursor + 1 // skip '\' char + chars, err := decodeKeyCharByEscapeCharStream(s) + if err != nil { + return nil, "", err + } + cursor = s.cursor + for _, c := range chars { + curBit &= bitmap[keyIdx][largeToSmallTable[c]] + if curBit == 0 { + s.cursor = cursor + return decodeKeyNotFoundStream(s, start) + } + keyIdx++ + } + default: + curBit &= bitmap[keyIdx][largeToSmallTable[c]] + if curBit == 0 { + s.cursor = cursor + return decodeKeyNotFoundStream(s, start) + } + keyIdx++ + } + cursor++ + } + default: + return nil, "", errors.ErrInvalidBeginningOfValue(char(p, cursor), s.totalOffset()) + } + } +} + +// decode from '\uXXXX' +func decodeKeyCharByUnicodeRuneStream(s *Stream) ([]byte, error) { + const defaultOffset = 4 + const surrogateOffset = 6 + + if s.cursor+defaultOffset >= s.length { + if !s.read() { + return nil, errors.ErrInvalidCharacter(s.char(), "escaped unicode char", s.totalOffset()) + } + } + + r := unicodeToRune(s.buf[s.cursor : s.cursor+defaultOffset]) + if utf16.IsSurrogate(r) { + s.cursor += defaultOffset + if s.cursor+surrogateOffset >= s.length { + s.read() + } + if s.cursor+surrogateOffset >= s.length || s.buf[s.cursor] != '\\' || s.buf[s.cursor+1] != 'u' { + s.cursor += defaultOffset - 1 + return []byte(string(unicode.ReplacementChar)), nil + } + r2 := unicodeToRune(s.buf[s.cursor+defaultOffset+2 : s.cursor+surrogateOffset]) + if r := utf16.DecodeRune(r, r2); r != unicode.ReplacementChar { + s.cursor += defaultOffset - 1 + return []byte(string(r)), nil + } + } + s.cursor += defaultOffset - 1 + return []byte(string(r)), nil +} + +func decodeKeyCharByEscapeCharStream(s *Stream) ([]byte, error) { + c := s.buf[s.cursor] + s.cursor++ +RETRY: + switch c { + case '"': + return []byte{'"'}, nil + case '\\': + return []byte{'\\'}, nil + case '/': + return []byte{'/'}, nil + case 'b': + return []byte{'\b'}, nil + case 'f': + return []byte{'\f'}, nil + case 'n': + return []byte{'\n'}, nil + case 'r': + return []byte{'\r'}, nil + case 't': + return []byte{'\t'}, nil + case 'u': + return decodeKeyCharByUnicodeRuneStream(s) + case nul: + if !s.read() { + return nil, errors.ErrInvalidCharacter(s.char(), "escaped char", s.totalOffset()) + } + goto RETRY + default: + return nil, errors.ErrUnexpectedEndOfJSON("struct field", s.totalOffset()) + } +} + +func decodeKeyNotFoundStream(s *Stream, start int64) (*structFieldSet, string, error) { + buf, cursor, p := s.stat() + for { + cursor++ + switch char(p, cursor) { + case '"': + b := buf[start:cursor] + key := *(*string)(unsafe.Pointer(&b)) + cursor++ + s.cursor = cursor + return nil, key, nil + case '\\': + cursor++ + if char(p, cursor) == nul { + s.cursor = cursor + if !s.read() { + return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset()) + } + buf, cursor, p = s.statForRetry() + } + case nul: + s.cursor = cursor + if !s.read() { + return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset()) + } + buf, cursor, p = s.statForRetry() + } + } +} + +func decodeKeyStream(d *structDecoder, s *Stream) (*structFieldSet, string, error) { + key, err := d.stringDecoder.decodeStreamByte(s) + if err != nil { + return nil, "", err + } + k := *(*string)(unsafe.Pointer(&key)) + return d.fieldMap[k], k, nil +} + +func (d *structDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error { + depth++ + if depth > maxDecodeNestingDepth { + return errors.ErrExceededMaxDepth(s.char(), s.cursor) + } + + c := s.skipWhiteSpace() + switch c { + case 'n': + if err := nullBytes(s); err != nil { + return err + } + return nil + default: + if s.char() != '{' { + return errors.ErrInvalidBeginningOfValue(s.char(), s.totalOffset()) + } + } + s.cursor++ + if s.skipWhiteSpace() == '}' { + s.cursor++ + return nil + } + var ( + seenFields map[int]struct{} + seenFieldNum int + ) + firstWin := (s.Option.Flags & FirstWinOption) != 0 + if firstWin { + seenFields = make(map[int]struct{}, d.fieldUniqueNameNum) + } + for { + s.reset() + field, key, err := d.keyStreamDecoder(d, s) + if err != nil { + return err + } + if s.skipWhiteSpace() != ':' { + return errors.ErrExpected("colon after object key", s.totalOffset()) + } + s.cursor++ + if field != nil { + if field.err != nil { + return field.err + } + if firstWin { + if _, exists := seenFields[field.fieldIdx]; exists { + if err := s.skipValue(depth); err != nil { + return err + } + } else { + if err := field.dec.DecodeStream(s, depth, unsafe.Pointer(uintptr(p)+field.offset)); err != nil { + return err + } + seenFieldNum++ + if d.fieldUniqueNameNum <= seenFieldNum { + return s.skipObject(depth) + } + seenFields[field.fieldIdx] = struct{}{} + } + } else { + if err := field.dec.DecodeStream(s, depth, unsafe.Pointer(uintptr(p)+field.offset)); err != nil { + return err + } + } + } else if s.DisallowUnknownFields { + return fmt.Errorf("json: unknown field %q", key) + } else { + if err := s.skipValue(depth); err != nil { + return err + } + } + c := s.skipWhiteSpace() + if c == '}' { + s.cursor++ + return nil + } + if c != ',' { + return errors.ErrExpected("comma after object element", s.totalOffset()) + } + s.cursor++ + } +} + +func (d *structDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { + buf := ctx.Buf + depth++ + if depth > maxDecodeNestingDepth { + return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor) + } + buflen := int64(len(buf)) + cursor = skipWhiteSpace(buf, cursor) + b := (*sliceHeader)(unsafe.Pointer(&buf)).data + switch char(b, cursor) { + case 'n': + if err := validateNull(buf, cursor); err != nil { + return 0, err + } + cursor += 4 + return cursor, nil + case '{': + default: + return 0, errors.ErrInvalidBeginningOfValue(char(b, cursor), cursor) + } + cursor++ + cursor = skipWhiteSpace(buf, cursor) + if buf[cursor] == '}' { + cursor++ + return cursor, nil + } + var ( + seenFields map[int]struct{} + seenFieldNum int + ) + firstWin := (ctx.Option.Flags & FirstWinOption) != 0 + if firstWin { + seenFields = make(map[int]struct{}, d.fieldUniqueNameNum) + } + for { + c, field, err := d.keyDecoder(d, buf, cursor) + if err != nil { + return 0, err + } + cursor = skipWhiteSpace(buf, c) + if char(b, cursor) != ':' { + return 0, errors.ErrExpected("colon after object key", cursor) + } + cursor++ + if cursor >= buflen { + return 0, errors.ErrExpected("object value after colon", cursor) + } + if field != nil { + if field.err != nil { + return 0, field.err + } + if firstWin { + if _, exists := seenFields[field.fieldIdx]; exists { + c, err := skipValue(buf, cursor, depth) + if err != nil { + return 0, err + } + cursor = c + } else { + c, err := field.dec.Decode(ctx, cursor, depth, unsafe.Pointer(uintptr(p)+field.offset)) + if err != nil { + return 0, err + } + cursor = c + seenFieldNum++ + if d.fieldUniqueNameNum <= seenFieldNum { + return skipObject(buf, cursor, depth) + } + seenFields[field.fieldIdx] = struct{}{} + } + } else { + c, err := field.dec.Decode(ctx, cursor, depth, unsafe.Pointer(uintptr(p)+field.offset)) + if err != nil { + return 0, err + } + cursor = c + } + } else { + c, err := skipValue(buf, cursor, depth) + if err != nil { + return 0, err + } + cursor = c + } + cursor = skipWhiteSpace(buf, cursor) + if char(b, cursor) == '}' { + cursor++ + return cursor, nil + } + if char(b, cursor) != ',' { + return 0, errors.ErrExpected("comma after object element", cursor) + } + cursor++ + } +} + +func (d *structDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) { + return nil, 0, fmt.Errorf("json: struct decoder does not support decode path") +} diff --git a/vendor/github.com/goccy/go-json/internal/decoder/type.go b/vendor/github.com/goccy/go-json/internal/decoder/type.go new file mode 100644 index 000000000..beaf3ab86 --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/decoder/type.go @@ -0,0 +1,30 @@ +package decoder + +import ( + "context" + "encoding" + "encoding/json" + "reflect" + "unsafe" +) + +type Decoder interface { + Decode(*RuntimeContext, int64, int64, unsafe.Pointer) (int64, error) + DecodePath(*RuntimeContext, int64, int64) ([][]byte, int64, error) + DecodeStream(*Stream, int64, unsafe.Pointer) error +} + +const ( + nul = '\000' + maxDecodeNestingDepth = 10000 +) + +type unmarshalerContext interface { + UnmarshalJSON(context.Context, []byte) error +} + +var ( + unmarshalJSONType = reflect.TypeOf((*json.Unmarshaler)(nil)).Elem() + unmarshalJSONContextType = reflect.TypeOf((*unmarshalerContext)(nil)).Elem() + unmarshalTextType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem() +) diff --git a/vendor/github.com/goccy/go-json/internal/decoder/uint.go b/vendor/github.com/goccy/go-json/internal/decoder/uint.go new file mode 100644 index 000000000..4131731b8 --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/decoder/uint.go @@ -0,0 +1,194 @@ +package decoder + +import ( + "fmt" + "reflect" + "unsafe" + + "github.com/goccy/go-json/internal/errors" + "github.com/goccy/go-json/internal/runtime" +) + +type uintDecoder struct { + typ *runtime.Type + kind reflect.Kind + op func(unsafe.Pointer, uint64) + structName string + fieldName string +} + +func newUintDecoder(typ *runtime.Type, structName, fieldName string, op func(unsafe.Pointer, uint64)) *uintDecoder { + return &uintDecoder{ + typ: typ, + kind: typ.Kind(), + op: op, + structName: structName, + fieldName: fieldName, + } +} + +func (d *uintDecoder) typeError(buf []byte, offset int64) *errors.UnmarshalTypeError { + return &errors.UnmarshalTypeError{ + Value: fmt.Sprintf("number %s", string(buf)), + Type: runtime.RType2Type(d.typ), + Offset: offset, + } +} + +var ( + pow10u64 = [...]uint64{ + 1e00, 1e01, 1e02, 1e03, 1e04, 1e05, 1e06, 1e07, 1e08, 1e09, + 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, + } + pow10u64Len = len(pow10u64) +) + +func (d *uintDecoder) parseUint(b []byte) (uint64, error) { + maxDigit := len(b) + if maxDigit > pow10u64Len { + return 0, fmt.Errorf("invalid length of number") + } + sum := uint64(0) + for i := 0; i < maxDigit; i++ { + c := uint64(b[i]) - 48 + digitValue := pow10u64[maxDigit-i-1] + sum += c * digitValue + } + return sum, nil +} + +func (d *uintDecoder) decodeStreamByte(s *Stream) ([]byte, error) { + for { + switch s.char() { + case ' ', '\n', '\t', '\r': + s.cursor++ + continue + case '0': + s.cursor++ + return numZeroBuf, nil + case '1', '2', '3', '4', '5', '6', '7', '8', '9': + start := s.cursor + for { + s.cursor++ + if numTable[s.char()] { + continue + } else if s.char() == nul { + if s.read() { + s.cursor-- // for retry current character + continue + } + } + break + } + num := s.buf[start:s.cursor] + return num, nil + case 'n': + if err := nullBytes(s); err != nil { + return nil, err + } + return nil, nil + case nul: + if s.read() { + continue + } + default: + return nil, d.typeError([]byte{s.char()}, s.totalOffset()) + } + break + } + return nil, errors.ErrUnexpectedEndOfJSON("number(unsigned integer)", s.totalOffset()) +} + +func (d *uintDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) { + for { + switch buf[cursor] { + case ' ', '\n', '\t', '\r': + cursor++ + continue + case '0': + cursor++ + return numZeroBuf, cursor, nil + case '1', '2', '3', '4', '5', '6', '7', '8', '9': + start := cursor + cursor++ + for numTable[buf[cursor]] { + cursor++ + } + num := buf[start:cursor] + return num, cursor, nil + case 'n': + if err := validateNull(buf, cursor); err != nil { + return nil, 0, err + } + cursor += 4 + return nil, cursor, nil + default: + return nil, 0, d.typeError([]byte{buf[cursor]}, cursor) + } + } +} + +func (d *uintDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error { + bytes, err := d.decodeStreamByte(s) + if err != nil { + return err + } + if bytes == nil { + return nil + } + u64, err := d.parseUint(bytes) + if err != nil { + return d.typeError(bytes, s.totalOffset()) + } + switch d.kind { + case reflect.Uint8: + if (1 << 8) <= u64 { + return d.typeError(bytes, s.totalOffset()) + } + case reflect.Uint16: + if (1 << 16) <= u64 { + return d.typeError(bytes, s.totalOffset()) + } + case reflect.Uint32: + if (1 << 32) <= u64 { + return d.typeError(bytes, s.totalOffset()) + } + } + d.op(p, u64) + return nil +} + +func (d *uintDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { + bytes, c, err := d.decodeByte(ctx.Buf, cursor) + if err != nil { + return 0, err + } + if bytes == nil { + return c, nil + } + cursor = c + u64, err := d.parseUint(bytes) + if err != nil { + return 0, d.typeError(bytes, cursor) + } + switch d.kind { + case reflect.Uint8: + if (1 << 8) <= u64 { + return 0, d.typeError(bytes, cursor) + } + case reflect.Uint16: + if (1 << 16) <= u64 { + return 0, d.typeError(bytes, cursor) + } + case reflect.Uint32: + if (1 << 32) <= u64 { + return 0, d.typeError(bytes, cursor) + } + } + d.op(p, u64) + return cursor, nil +} + +func (d *uintDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) { + return nil, 0, fmt.Errorf("json: uint decoder does not support decode path") +} diff --git a/vendor/github.com/goccy/go-json/internal/decoder/unmarshal_json.go b/vendor/github.com/goccy/go-json/internal/decoder/unmarshal_json.go new file mode 100644 index 000000000..4cd6dbd57 --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/decoder/unmarshal_json.go @@ -0,0 +1,104 @@ +package decoder + +import ( + "context" + "encoding/json" + "fmt" + "unsafe" + + "github.com/goccy/go-json/internal/errors" + "github.com/goccy/go-json/internal/runtime" +) + +type unmarshalJSONDecoder struct { + typ *runtime.Type + structName string + fieldName string +} + +func newUnmarshalJSONDecoder(typ *runtime.Type, structName, fieldName string) *unmarshalJSONDecoder { + return &unmarshalJSONDecoder{ + typ: typ, + structName: structName, + fieldName: fieldName, + } +} + +func (d *unmarshalJSONDecoder) annotateError(cursor int64, err error) { + switch e := err.(type) { + case *errors.UnmarshalTypeError: + e.Struct = d.structName + e.Field = d.fieldName + case *errors.SyntaxError: + e.Offset = cursor + } +} + +func (d *unmarshalJSONDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error { + s.skipWhiteSpace() + start := s.cursor + if err := s.skipValue(depth); err != nil { + return err + } + src := s.buf[start:s.cursor] + dst := make([]byte, len(src)) + copy(dst, src) + + v := *(*interface{})(unsafe.Pointer(&emptyInterface{ + typ: d.typ, + ptr: p, + })) + switch v := v.(type) { + case unmarshalerContext: + var ctx context.Context + if (s.Option.Flags & ContextOption) != 0 { + ctx = s.Option.Context + } else { + ctx = context.Background() + } + if err := v.UnmarshalJSON(ctx, dst); err != nil { + d.annotateError(s.cursor, err) + return err + } + case json.Unmarshaler: + if err := v.UnmarshalJSON(dst); err != nil { + d.annotateError(s.cursor, err) + return err + } + } + return nil +} + +func (d *unmarshalJSONDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { + buf := ctx.Buf + cursor = skipWhiteSpace(buf, cursor) + start := cursor + end, err := skipValue(buf, cursor, depth) + if err != nil { + return 0, err + } + src := buf[start:end] + dst := make([]byte, len(src)) + copy(dst, src) + + v := *(*interface{})(unsafe.Pointer(&emptyInterface{ + typ: d.typ, + ptr: p, + })) + if (ctx.Option.Flags & ContextOption) != 0 { + if err := v.(unmarshalerContext).UnmarshalJSON(ctx.Option.Context, dst); err != nil { + d.annotateError(cursor, err) + return 0, err + } + } else { + if err := v.(json.Unmarshaler).UnmarshalJSON(dst); err != nil { + d.annotateError(cursor, err) + return 0, err + } + } + return end, nil +} + +func (d *unmarshalJSONDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) { + return nil, 0, fmt.Errorf("json: unmarshal json decoder does not support decode path") +} diff --git a/vendor/github.com/goccy/go-json/internal/decoder/unmarshal_text.go b/vendor/github.com/goccy/go-json/internal/decoder/unmarshal_text.go new file mode 100644 index 000000000..6d37993f0 --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/decoder/unmarshal_text.go @@ -0,0 +1,285 @@ +package decoder + +import ( + "bytes" + "encoding" + "fmt" + "unicode" + "unicode/utf16" + "unicode/utf8" + "unsafe" + + "github.com/goccy/go-json/internal/errors" + "github.com/goccy/go-json/internal/runtime" +) + +type unmarshalTextDecoder struct { + typ *runtime.Type + structName string + fieldName string +} + +func newUnmarshalTextDecoder(typ *runtime.Type, structName, fieldName string) *unmarshalTextDecoder { + return &unmarshalTextDecoder{ + typ: typ, + structName: structName, + fieldName: fieldName, + } +} + +func (d *unmarshalTextDecoder) annotateError(cursor int64, err error) { + switch e := err.(type) { + case *errors.UnmarshalTypeError: + e.Struct = d.structName + e.Field = d.fieldName + case *errors.SyntaxError: + e.Offset = cursor + } +} + +var ( + nullbytes = []byte(`null`) +) + +func (d *unmarshalTextDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error { + s.skipWhiteSpace() + start := s.cursor + if err := s.skipValue(depth); err != nil { + return err + } + src := s.buf[start:s.cursor] + if len(src) > 0 { + switch src[0] { + case '[': + return &errors.UnmarshalTypeError{ + Value: "array", + Type: runtime.RType2Type(d.typ), + Offset: s.totalOffset(), + } + case '{': + return &errors.UnmarshalTypeError{ + Value: "object", + Type: runtime.RType2Type(d.typ), + Offset: s.totalOffset(), + } + case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + return &errors.UnmarshalTypeError{ + Value: "number", + Type: runtime.RType2Type(d.typ), + Offset: s.totalOffset(), + } + case 'n': + if bytes.Equal(src, nullbytes) { + *(*unsafe.Pointer)(p) = nil + return nil + } + } + } + dst := make([]byte, len(src)) + copy(dst, src) + + if b, ok := unquoteBytes(dst); ok { + dst = b + } + v := *(*interface{})(unsafe.Pointer(&emptyInterface{ + typ: d.typ, + ptr: p, + })) + if err := v.(encoding.TextUnmarshaler).UnmarshalText(dst); err != nil { + d.annotateError(s.cursor, err) + return err + } + return nil +} + +func (d *unmarshalTextDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { + buf := ctx.Buf + cursor = skipWhiteSpace(buf, cursor) + start := cursor + end, err := skipValue(buf, cursor, depth) + if err != nil { + return 0, err + } + src := buf[start:end] + if len(src) > 0 { + switch src[0] { + case '[': + return 0, &errors.UnmarshalTypeError{ + Value: "array", + Type: runtime.RType2Type(d.typ), + Offset: start, + } + case '{': + return 0, &errors.UnmarshalTypeError{ + Value: "object", + Type: runtime.RType2Type(d.typ), + Offset: start, + } + case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + return 0, &errors.UnmarshalTypeError{ + Value: "number", + Type: runtime.RType2Type(d.typ), + Offset: start, + } + case 'n': + if bytes.Equal(src, nullbytes) { + *(*unsafe.Pointer)(p) = nil + return end, nil + } + } + } + + if s, ok := unquoteBytes(src); ok { + src = s + } + v := *(*interface{})(unsafe.Pointer(&emptyInterface{ + typ: d.typ, + ptr: *(*unsafe.Pointer)(unsafe.Pointer(&p)), + })) + if err := v.(encoding.TextUnmarshaler).UnmarshalText(src); err != nil { + d.annotateError(cursor, err) + return 0, err + } + return end, nil +} + +func (d *unmarshalTextDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) { + return nil, 0, fmt.Errorf("json: unmarshal text decoder does not support decode path") +} + +func unquoteBytes(s []byte) (t []byte, ok bool) { + length := len(s) + if length < 2 || s[0] != '"' || s[length-1] != '"' { + return + } + s = s[1 : length-1] + length -= 2 + + // Check for unusual characters. If there are none, + // then no unquoting is needed, so return a slice of the + // original bytes. + r := 0 + for r < length { + c := s[r] + if c == '\\' || c == '"' || c < ' ' { + break + } + if c < utf8.RuneSelf { + r++ + continue + } + rr, size := utf8.DecodeRune(s[r:]) + if rr == utf8.RuneError && size == 1 { + break + } + r += size + } + if r == length { + return s, true + } + + b := make([]byte, length+2*utf8.UTFMax) + w := copy(b, s[0:r]) + for r < length { + // Out of room? Can only happen if s is full of + // malformed UTF-8 and we're replacing each + // byte with RuneError. + if w >= len(b)-2*utf8.UTFMax { + nb := make([]byte, (len(b)+utf8.UTFMax)*2) + copy(nb, b[0:w]) + b = nb + } + switch c := s[r]; { + case c == '\\': + r++ + if r >= length { + return + } + switch s[r] { + default: + return + case '"', '\\', '/', '\'': + b[w] = s[r] + r++ + w++ + case 'b': + b[w] = '\b' + r++ + w++ + case 'f': + b[w] = '\f' + r++ + w++ + case 'n': + b[w] = '\n' + r++ + w++ + case 'r': + b[w] = '\r' + r++ + w++ + case 't': + b[w] = '\t' + r++ + w++ + case 'u': + r-- + rr := getu4(s[r:]) + if rr < 0 { + return + } + r += 6 + if utf16.IsSurrogate(rr) { + rr1 := getu4(s[r:]) + if dec := utf16.DecodeRune(rr, rr1); dec != unicode.ReplacementChar { + // A valid pair; consume. + r += 6 + w += utf8.EncodeRune(b[w:], dec) + break + } + // Invalid surrogate; fall back to replacement rune. + rr = unicode.ReplacementChar + } + w += utf8.EncodeRune(b[w:], rr) + } + + // Quote, control characters are invalid. + case c == '"', c < ' ': + return + + // ASCII + case c < utf8.RuneSelf: + b[w] = c + r++ + w++ + + // Coerce to well-formed UTF-8. + default: + rr, size := utf8.DecodeRune(s[r:]) + r += size + w += utf8.EncodeRune(b[w:], rr) + } + } + return b[0:w], true +} + +func getu4(s []byte) rune { + if len(s) < 6 || s[0] != '\\' || s[1] != 'u' { + return -1 + } + var r rune + for _, c := range s[2:6] { + switch { + case '0' <= c && c <= '9': + c = c - '0' + case 'a' <= c && c <= 'f': + c = c - 'a' + 10 + case 'A' <= c && c <= 'F': + c = c - 'A' + 10 + default: + return -1 + } + r = r*16 + rune(c) + } + return r +} diff --git a/vendor/github.com/goccy/go-json/internal/decoder/wrapped_string.go b/vendor/github.com/goccy/go-json/internal/decoder/wrapped_string.go new file mode 100644 index 000000000..0c4e2e6ea --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/decoder/wrapped_string.go @@ -0,0 +1,73 @@ +package decoder + +import ( + "fmt" + "reflect" + "unsafe" + + "github.com/goccy/go-json/internal/runtime" +) + +type wrappedStringDecoder struct { + typ *runtime.Type + dec Decoder + stringDecoder *stringDecoder + structName string + fieldName string + isPtrType bool +} + +func newWrappedStringDecoder(typ *runtime.Type, dec Decoder, structName, fieldName string) *wrappedStringDecoder { + return &wrappedStringDecoder{ + typ: typ, + dec: dec, + stringDecoder: newStringDecoder(structName, fieldName), + structName: structName, + fieldName: fieldName, + isPtrType: typ.Kind() == reflect.Ptr, + } +} + +func (d *wrappedStringDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error { + bytes, err := d.stringDecoder.decodeStreamByte(s) + if err != nil { + return err + } + if bytes == nil { + if d.isPtrType { + *(*unsafe.Pointer)(p) = nil + } + return nil + } + b := make([]byte, len(bytes)+1) + copy(b, bytes) + if _, err := d.dec.Decode(&RuntimeContext{Buf: b}, 0, depth, p); err != nil { + return err + } + return nil +} + +func (d *wrappedStringDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { + bytes, c, err := d.stringDecoder.decodeByte(ctx.Buf, cursor) + if err != nil { + return 0, err + } + if bytes == nil { + if d.isPtrType { + *(*unsafe.Pointer)(p) = nil + } + return c, nil + } + bytes = append(bytes, nul) + oldBuf := ctx.Buf + ctx.Buf = bytes + if _, err := d.dec.Decode(ctx, 0, depth, p); err != nil { + return 0, err + } + ctx.Buf = oldBuf + return c, nil +} + +func (d *wrappedStringDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) { + return nil, 0, fmt.Errorf("json: wrapped string decoder does not support decode path") +} diff --git a/vendor/github.com/goccy/go-json/internal/encoder/code.go b/vendor/github.com/goccy/go-json/internal/encoder/code.go new file mode 100644 index 000000000..5b08faefc --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/encoder/code.go @@ -0,0 +1,1023 @@ +package encoder + +import ( + "fmt" + "reflect" + "unsafe" + + "github.com/goccy/go-json/internal/runtime" +) + +type Code interface { + Kind() CodeKind + ToOpcode(*compileContext) Opcodes + Filter(*FieldQuery) Code +} + +type AnonymousCode interface { + ToAnonymousOpcode(*compileContext) Opcodes +} + +type Opcodes []*Opcode + +func (o Opcodes) First() *Opcode { + if len(o) == 0 { + return nil + } + return o[0] +} + +func (o Opcodes) Last() *Opcode { + if len(o) == 0 { + return nil + } + return o[len(o)-1] +} + +func (o Opcodes) Add(codes ...*Opcode) Opcodes { + return append(o, codes...) +} + +type CodeKind int + +const ( + CodeKindInterface CodeKind = iota + CodeKindPtr + CodeKindInt + CodeKindUint + CodeKindFloat + CodeKindString + CodeKindBool + CodeKindStruct + CodeKindMap + CodeKindSlice + CodeKindArray + CodeKindBytes + CodeKindMarshalJSON + CodeKindMarshalText + CodeKindRecursive +) + +type IntCode struct { + typ *runtime.Type + bitSize uint8 + isString bool + isPtr bool +} + +func (c *IntCode) Kind() CodeKind { + return CodeKindInt +} + +func (c *IntCode) ToOpcode(ctx *compileContext) Opcodes { + var code *Opcode + switch { + case c.isPtr: + code = newOpCode(ctx, c.typ, OpIntPtr) + case c.isString: + code = newOpCode(ctx, c.typ, OpIntString) + default: + code = newOpCode(ctx, c.typ, OpInt) + } + code.NumBitSize = c.bitSize + ctx.incIndex() + return Opcodes{code} +} + +func (c *IntCode) Filter(_ *FieldQuery) Code { + return c +} + +type UintCode struct { + typ *runtime.Type + bitSize uint8 + isString bool + isPtr bool +} + +func (c *UintCode) Kind() CodeKind { + return CodeKindUint +} + +func (c *UintCode) ToOpcode(ctx *compileContext) Opcodes { + var code *Opcode + switch { + case c.isPtr: + code = newOpCode(ctx, c.typ, OpUintPtr) + case c.isString: + code = newOpCode(ctx, c.typ, OpUintString) + default: + code = newOpCode(ctx, c.typ, OpUint) + } + code.NumBitSize = c.bitSize + ctx.incIndex() + return Opcodes{code} +} + +func (c *UintCode) Filter(_ *FieldQuery) Code { + return c +} + +type FloatCode struct { + typ *runtime.Type + bitSize uint8 + isPtr bool +} + +func (c *FloatCode) Kind() CodeKind { + return CodeKindFloat +} + +func (c *FloatCode) ToOpcode(ctx *compileContext) Opcodes { + var code *Opcode + switch { + case c.isPtr: + switch c.bitSize { + case 32: + code = newOpCode(ctx, c.typ, OpFloat32Ptr) + default: + code = newOpCode(ctx, c.typ, OpFloat64Ptr) + } + default: + switch c.bitSize { + case 32: + code = newOpCode(ctx, c.typ, OpFloat32) + default: + code = newOpCode(ctx, c.typ, OpFloat64) + } + } + ctx.incIndex() + return Opcodes{code} +} + +func (c *FloatCode) Filter(_ *FieldQuery) Code { + return c +} + +type StringCode struct { + typ *runtime.Type + isPtr bool +} + +func (c *StringCode) Kind() CodeKind { + return CodeKindString +} + +func (c *StringCode) ToOpcode(ctx *compileContext) Opcodes { + isJSONNumberType := c.typ == runtime.Type2RType(jsonNumberType) + var code *Opcode + if c.isPtr { + if isJSONNumberType { + code = newOpCode(ctx, c.typ, OpNumberPtr) + } else { + code = newOpCode(ctx, c.typ, OpStringPtr) + } + } else { + if isJSONNumberType { + code = newOpCode(ctx, c.typ, OpNumber) + } else { + code = newOpCode(ctx, c.typ, OpString) + } + } + ctx.incIndex() + return Opcodes{code} +} + +func (c *StringCode) Filter(_ *FieldQuery) Code { + return c +} + +type BoolCode struct { + typ *runtime.Type + isPtr bool +} + +func (c *BoolCode) Kind() CodeKind { + return CodeKindBool +} + +func (c *BoolCode) ToOpcode(ctx *compileContext) Opcodes { + var code *Opcode + switch { + case c.isPtr: + code = newOpCode(ctx, c.typ, OpBoolPtr) + default: + code = newOpCode(ctx, c.typ, OpBool) + } + ctx.incIndex() + return Opcodes{code} +} + +func (c *BoolCode) Filter(_ *FieldQuery) Code { + return c +} + +type BytesCode struct { + typ *runtime.Type + isPtr bool +} + +func (c *BytesCode) Kind() CodeKind { + return CodeKindBytes +} + +func (c *BytesCode) ToOpcode(ctx *compileContext) Opcodes { + var code *Opcode + switch { + case c.isPtr: + code = newOpCode(ctx, c.typ, OpBytesPtr) + default: + code = newOpCode(ctx, c.typ, OpBytes) + } + ctx.incIndex() + return Opcodes{code} +} + +func (c *BytesCode) Filter(_ *FieldQuery) Code { + return c +} + +type SliceCode struct { + typ *runtime.Type + value Code +} + +func (c *SliceCode) Kind() CodeKind { + return CodeKindSlice +} + +func (c *SliceCode) ToOpcode(ctx *compileContext) Opcodes { + // header => opcode => elem => end + // ^ | + // |________| + size := c.typ.Elem().Size() + header := newSliceHeaderCode(ctx, c.typ) + ctx.incIndex() + + ctx.incIndent() + codes := c.value.ToOpcode(ctx) + ctx.decIndent() + + codes.First().Flags |= IndirectFlags + elemCode := newSliceElemCode(ctx, c.typ.Elem(), header, size) + ctx.incIndex() + end := newOpCode(ctx, c.typ, OpSliceEnd) + ctx.incIndex() + header.End = end + header.Next = codes.First() + codes.Last().Next = elemCode + elemCode.Next = codes.First() + elemCode.End = end + return Opcodes{header}.Add(codes...).Add(elemCode).Add(end) +} + +func (c *SliceCode) Filter(_ *FieldQuery) Code { + return c +} + +type ArrayCode struct { + typ *runtime.Type + value Code +} + +func (c *ArrayCode) Kind() CodeKind { + return CodeKindArray +} + +func (c *ArrayCode) ToOpcode(ctx *compileContext) Opcodes { + // header => opcode => elem => end + // ^ | + // |________| + elem := c.typ.Elem() + alen := c.typ.Len() + size := elem.Size() + + header := newArrayHeaderCode(ctx, c.typ, alen) + ctx.incIndex() + + ctx.incIndent() + codes := c.value.ToOpcode(ctx) + ctx.decIndent() + + codes.First().Flags |= IndirectFlags + + elemCode := newArrayElemCode(ctx, elem, header, alen, size) + ctx.incIndex() + + end := newOpCode(ctx, c.typ, OpArrayEnd) + ctx.incIndex() + + header.End = end + header.Next = codes.First() + codes.Last().Next = elemCode + elemCode.Next = codes.First() + elemCode.End = end + + return Opcodes{header}.Add(codes...).Add(elemCode).Add(end) +} + +func (c *ArrayCode) Filter(_ *FieldQuery) Code { + return c +} + +type MapCode struct { + typ *runtime.Type + key Code + value Code +} + +func (c *MapCode) Kind() CodeKind { + return CodeKindMap +} + +func (c *MapCode) ToOpcode(ctx *compileContext) Opcodes { + // header => code => value => code => key => code => value => code => end + // ^ | + // |_______________________| + header := newMapHeaderCode(ctx, c.typ) + ctx.incIndex() + + keyCodes := c.key.ToOpcode(ctx) + + value := newMapValueCode(ctx, c.typ.Elem(), header) + ctx.incIndex() + + ctx.incIndent() + valueCodes := c.value.ToOpcode(ctx) + ctx.decIndent() + + valueCodes.First().Flags |= IndirectFlags + + key := newMapKeyCode(ctx, c.typ.Key(), header) + ctx.incIndex() + + end := newMapEndCode(ctx, c.typ, header) + ctx.incIndex() + + header.Next = keyCodes.First() + keyCodes.Last().Next = value + value.Next = valueCodes.First() + valueCodes.Last().Next = key + key.Next = keyCodes.First() + + header.End = end + key.End = end + value.End = end + return Opcodes{header}.Add(keyCodes...).Add(value).Add(valueCodes...).Add(key).Add(end) +} + +func (c *MapCode) Filter(_ *FieldQuery) Code { + return c +} + +type StructCode struct { + typ *runtime.Type + fields []*StructFieldCode + isPtr bool + disableIndirectConversion bool + isIndirect bool + isRecursive bool +} + +func (c *StructCode) Kind() CodeKind { + return CodeKindStruct +} + +func (c *StructCode) lastFieldCode(field *StructFieldCode, firstField *Opcode) *Opcode { + if isEmbeddedStruct(field) { + return c.lastAnonymousFieldCode(firstField) + } + lastField := firstField + for lastField.NextField != nil { + lastField = lastField.NextField + } + return lastField +} + +func (c *StructCode) lastAnonymousFieldCode(firstField *Opcode) *Opcode { + // firstField is special StructHead operation for anonymous structure. + // So, StructHead's next operation is truly struct head operation. + for firstField.Op == OpStructHead || firstField.Op == OpStructField { + firstField = firstField.Next + } + lastField := firstField + for lastField.NextField != nil { + lastField = lastField.NextField + } + return lastField +} + +func (c *StructCode) ToOpcode(ctx *compileContext) Opcodes { + // header => code => structField => code => end + // ^ | + // |__________| + if c.isRecursive { + recursive := newRecursiveCode(ctx, c.typ, &CompiledCode{}) + recursive.Type = c.typ + ctx.incIndex() + *ctx.recursiveCodes = append(*ctx.recursiveCodes, recursive) + return Opcodes{recursive} + } + codes := Opcodes{} + var prevField *Opcode + ctx.incIndent() + for idx, field := range c.fields { + isFirstField := idx == 0 + isEndField := idx == len(c.fields)-1 + fieldCodes := field.ToOpcode(ctx, isFirstField, isEndField) + for _, code := range fieldCodes { + if c.isIndirect { + code.Flags |= IndirectFlags + } + } + firstField := fieldCodes.First() + if len(codes) > 0 { + codes.Last().Next = firstField + firstField.Idx = codes.First().Idx + } + if prevField != nil { + prevField.NextField = firstField + } + if isEndField { + endField := fieldCodes.Last() + if len(codes) > 0 { + codes.First().End = endField + } else { + firstField.End = endField + } + codes = codes.Add(fieldCodes...) + break + } + prevField = c.lastFieldCode(field, firstField) + codes = codes.Add(fieldCodes...) + } + if len(codes) == 0 { + head := &Opcode{ + Op: OpStructHead, + Idx: opcodeOffset(ctx.ptrIndex), + Type: c.typ, + DisplayIdx: ctx.opcodeIndex, + Indent: ctx.indent, + } + ctx.incOpcodeIndex() + end := &Opcode{ + Op: OpStructEnd, + Idx: opcodeOffset(ctx.ptrIndex), + DisplayIdx: ctx.opcodeIndex, + Indent: ctx.indent, + } + head.NextField = end + head.Next = end + head.End = end + codes = codes.Add(head, end) + ctx.incIndex() + } + ctx.decIndent() + ctx.structTypeToCodes[uintptr(unsafe.Pointer(c.typ))] = codes + return codes +} + +func (c *StructCode) ToAnonymousOpcode(ctx *compileContext) Opcodes { + // header => code => structField => code => end + // ^ | + // |__________| + if c.isRecursive { + recursive := newRecursiveCode(ctx, c.typ, &CompiledCode{}) + recursive.Type = c.typ + ctx.incIndex() + *ctx.recursiveCodes = append(*ctx.recursiveCodes, recursive) + return Opcodes{recursive} + } + codes := Opcodes{} + var prevField *Opcode + for idx, field := range c.fields { + isFirstField := idx == 0 + isEndField := idx == len(c.fields)-1 + fieldCodes := field.ToAnonymousOpcode(ctx, isFirstField, isEndField) + for _, code := range fieldCodes { + if c.isIndirect { + code.Flags |= IndirectFlags + } + } + firstField := fieldCodes.First() + if len(codes) > 0 { + codes.Last().Next = firstField + firstField.Idx = codes.First().Idx + } + if prevField != nil { + prevField.NextField = firstField + } + if isEndField { + lastField := fieldCodes.Last() + if len(codes) > 0 { + codes.First().End = lastField + } else { + firstField.End = lastField + } + } + prevField = firstField + codes = codes.Add(fieldCodes...) + } + return codes +} + +func (c *StructCode) removeFieldsByTags(tags runtime.StructTags) { + fields := make([]*StructFieldCode, 0, len(c.fields)) + for _, field := range c.fields { + if field.isAnonymous { + structCode := field.getAnonymousStruct() + if structCode != nil && !structCode.isRecursive { + structCode.removeFieldsByTags(tags) + if len(structCode.fields) > 0 { + fields = append(fields, field) + } + continue + } + } + if tags.ExistsKey(field.key) { + continue + } + fields = append(fields, field) + } + c.fields = fields +} + +func (c *StructCode) enableIndirect() { + if c.isIndirect { + return + } + c.isIndirect = true + if len(c.fields) == 0 { + return + } + structCode := c.fields[0].getStruct() + if structCode == nil { + return + } + structCode.enableIndirect() +} + +func (c *StructCode) Filter(query *FieldQuery) Code { + fieldMap := map[string]*FieldQuery{} + for _, field := range query.Fields { + fieldMap[field.Name] = field + } + fields := make([]*StructFieldCode, 0, len(c.fields)) + for _, field := range c.fields { + query, exists := fieldMap[field.key] + if !exists { + continue + } + fieldCode := &StructFieldCode{ + typ: field.typ, + key: field.key, + tag: field.tag, + value: field.value, + offset: field.offset, + isAnonymous: field.isAnonymous, + isTaggedKey: field.isTaggedKey, + isNilableType: field.isNilableType, + isNilCheck: field.isNilCheck, + isAddrForMarshaler: field.isAddrForMarshaler, + isNextOpPtrType: field.isNextOpPtrType, + } + if len(query.Fields) > 0 { + fieldCode.value = fieldCode.value.Filter(query) + } + fields = append(fields, fieldCode) + } + return &StructCode{ + typ: c.typ, + fields: fields, + isPtr: c.isPtr, + disableIndirectConversion: c.disableIndirectConversion, + isIndirect: c.isIndirect, + isRecursive: c.isRecursive, + } +} + +type StructFieldCode struct { + typ *runtime.Type + key string + tag *runtime.StructTag + value Code + offset uintptr + isAnonymous bool + isTaggedKey bool + isNilableType bool + isNilCheck bool + isAddrForMarshaler bool + isNextOpPtrType bool + isMarshalerContext bool +} + +func (c *StructFieldCode) getStruct() *StructCode { + value := c.value + ptr, ok := value.(*PtrCode) + if ok { + value = ptr.value + } + structCode, ok := value.(*StructCode) + if ok { + return structCode + } + return nil +} + +func (c *StructFieldCode) getAnonymousStruct() *StructCode { + if !c.isAnonymous { + return nil + } + return c.getStruct() +} + +func optimizeStructHeader(code *Opcode, tag *runtime.StructTag) OpType { + headType := code.ToHeaderType(tag.IsString) + if tag.IsOmitEmpty { + headType = headType.HeadToOmitEmptyHead() + } + return headType +} + +func optimizeStructField(code *Opcode, tag *runtime.StructTag) OpType { + fieldType := code.ToFieldType(tag.IsString) + if tag.IsOmitEmpty { + fieldType = fieldType.FieldToOmitEmptyField() + } + return fieldType +} + +func (c *StructFieldCode) headerOpcodes(ctx *compileContext, field *Opcode, valueCodes Opcodes) Opcodes { + value := valueCodes.First() + op := optimizeStructHeader(value, c.tag) + field.Op = op + if value.Flags&MarshalerContextFlags != 0 { + field.Flags |= MarshalerContextFlags + } + field.NumBitSize = value.NumBitSize + field.PtrNum = value.PtrNum + field.FieldQuery = value.FieldQuery + fieldCodes := Opcodes{field} + if op.IsMultipleOpHead() { + field.Next = value + fieldCodes = fieldCodes.Add(valueCodes...) + } else { + ctx.decIndex() + } + return fieldCodes +} + +func (c *StructFieldCode) fieldOpcodes(ctx *compileContext, field *Opcode, valueCodes Opcodes) Opcodes { + value := valueCodes.First() + op := optimizeStructField(value, c.tag) + field.Op = op + if value.Flags&MarshalerContextFlags != 0 { + field.Flags |= MarshalerContextFlags + } + field.NumBitSize = value.NumBitSize + field.PtrNum = value.PtrNum + field.FieldQuery = value.FieldQuery + + fieldCodes := Opcodes{field} + if op.IsMultipleOpField() { + field.Next = value + fieldCodes = fieldCodes.Add(valueCodes...) + } else { + ctx.decIndex() + } + return fieldCodes +} + +func (c *StructFieldCode) addStructEndCode(ctx *compileContext, codes Opcodes) Opcodes { + end := &Opcode{ + Op: OpStructEnd, + Idx: opcodeOffset(ctx.ptrIndex), + DisplayIdx: ctx.opcodeIndex, + Indent: ctx.indent, + } + codes.Last().Next = end + code := codes.First() + for code.Op == OpStructField || code.Op == OpStructHead { + code = code.Next + } + for code.NextField != nil { + code = code.NextField + } + code.NextField = end + + codes = codes.Add(end) + ctx.incOpcodeIndex() + return codes +} + +func (c *StructFieldCode) structKey(ctx *compileContext) string { + if ctx.escapeKey { + rctx := &RuntimeContext{Option: &Option{Flag: HTMLEscapeOption}} + return fmt.Sprintf(`%s:`, string(AppendString(rctx, []byte{}, c.key))) + } + return fmt.Sprintf(`"%s":`, c.key) +} + +func (c *StructFieldCode) flags() OpFlags { + var flags OpFlags + if c.isTaggedKey { + flags |= IsTaggedKeyFlags + } + if c.isNilableType { + flags |= IsNilableTypeFlags + } + if c.isNilCheck { + flags |= NilCheckFlags + } + if c.isAddrForMarshaler { + flags |= AddrForMarshalerFlags + } + if c.isNextOpPtrType { + flags |= IsNextOpPtrTypeFlags + } + if c.isAnonymous { + flags |= AnonymousKeyFlags + } + if c.isMarshalerContext { + flags |= MarshalerContextFlags + } + return flags +} + +func (c *StructFieldCode) toValueOpcodes(ctx *compileContext) Opcodes { + if c.isAnonymous { + anonymCode, ok := c.value.(AnonymousCode) + if ok { + return anonymCode.ToAnonymousOpcode(ctx) + } + } + return c.value.ToOpcode(ctx) +} + +func (c *StructFieldCode) ToOpcode(ctx *compileContext, isFirstField, isEndField bool) Opcodes { + field := &Opcode{ + Idx: opcodeOffset(ctx.ptrIndex), + Flags: c.flags(), + Key: c.structKey(ctx), + Offset: uint32(c.offset), + Type: c.typ, + DisplayIdx: ctx.opcodeIndex, + Indent: ctx.indent, + DisplayKey: c.key, + } + ctx.incIndex() + valueCodes := c.toValueOpcodes(ctx) + if isFirstField { + codes := c.headerOpcodes(ctx, field, valueCodes) + if isEndField { + codes = c.addStructEndCode(ctx, codes) + } + return codes + } + codes := c.fieldOpcodes(ctx, field, valueCodes) + if isEndField { + if isEnableStructEndOptimization(c.value) { + field.Op = field.Op.FieldToEnd() + } else { + codes = c.addStructEndCode(ctx, codes) + } + } + return codes +} + +func (c *StructFieldCode) ToAnonymousOpcode(ctx *compileContext, isFirstField, isEndField bool) Opcodes { + field := &Opcode{ + Idx: opcodeOffset(ctx.ptrIndex), + Flags: c.flags() | AnonymousHeadFlags, + Key: c.structKey(ctx), + Offset: uint32(c.offset), + Type: c.typ, + DisplayIdx: ctx.opcodeIndex, + Indent: ctx.indent, + DisplayKey: c.key, + } + ctx.incIndex() + valueCodes := c.toValueOpcodes(ctx) + if isFirstField { + return c.headerOpcodes(ctx, field, valueCodes) + } + return c.fieldOpcodes(ctx, field, valueCodes) +} + +func isEnableStructEndOptimization(value Code) bool { + switch value.Kind() { + case CodeKindInt, + CodeKindUint, + CodeKindFloat, + CodeKindString, + CodeKindBool, + CodeKindBytes: + return true + case CodeKindPtr: + return isEnableStructEndOptimization(value.(*PtrCode).value) + default: + return false + } +} + +type InterfaceCode struct { + typ *runtime.Type + fieldQuery *FieldQuery + isPtr bool +} + +func (c *InterfaceCode) Kind() CodeKind { + return CodeKindInterface +} + +func (c *InterfaceCode) ToOpcode(ctx *compileContext) Opcodes { + var code *Opcode + switch { + case c.isPtr: + code = newOpCode(ctx, c.typ, OpInterfacePtr) + default: + code = newOpCode(ctx, c.typ, OpInterface) + } + code.FieldQuery = c.fieldQuery + if c.typ.NumMethod() > 0 { + code.Flags |= NonEmptyInterfaceFlags + } + ctx.incIndex() + return Opcodes{code} +} + +func (c *InterfaceCode) Filter(query *FieldQuery) Code { + return &InterfaceCode{ + typ: c.typ, + fieldQuery: query, + isPtr: c.isPtr, + } +} + +type MarshalJSONCode struct { + typ *runtime.Type + fieldQuery *FieldQuery + isAddrForMarshaler bool + isNilableType bool + isMarshalerContext bool +} + +func (c *MarshalJSONCode) Kind() CodeKind { + return CodeKindMarshalJSON +} + +func (c *MarshalJSONCode) ToOpcode(ctx *compileContext) Opcodes { + code := newOpCode(ctx, c.typ, OpMarshalJSON) + code.FieldQuery = c.fieldQuery + if c.isAddrForMarshaler { + code.Flags |= AddrForMarshalerFlags + } + if c.isMarshalerContext { + code.Flags |= MarshalerContextFlags + } + if c.isNilableType { + code.Flags |= IsNilableTypeFlags + } else { + code.Flags &= ^IsNilableTypeFlags + } + ctx.incIndex() + return Opcodes{code} +} + +func (c *MarshalJSONCode) Filter(query *FieldQuery) Code { + return &MarshalJSONCode{ + typ: c.typ, + fieldQuery: query, + isAddrForMarshaler: c.isAddrForMarshaler, + isNilableType: c.isNilableType, + isMarshalerContext: c.isMarshalerContext, + } +} + +type MarshalTextCode struct { + typ *runtime.Type + fieldQuery *FieldQuery + isAddrForMarshaler bool + isNilableType bool +} + +func (c *MarshalTextCode) Kind() CodeKind { + return CodeKindMarshalText +} + +func (c *MarshalTextCode) ToOpcode(ctx *compileContext) Opcodes { + code := newOpCode(ctx, c.typ, OpMarshalText) + code.FieldQuery = c.fieldQuery + if c.isAddrForMarshaler { + code.Flags |= AddrForMarshalerFlags + } + if c.isNilableType { + code.Flags |= IsNilableTypeFlags + } else { + code.Flags &= ^IsNilableTypeFlags + } + ctx.incIndex() + return Opcodes{code} +} + +func (c *MarshalTextCode) Filter(query *FieldQuery) Code { + return &MarshalTextCode{ + typ: c.typ, + fieldQuery: query, + isAddrForMarshaler: c.isAddrForMarshaler, + isNilableType: c.isNilableType, + } +} + +type PtrCode struct { + typ *runtime.Type + value Code + ptrNum uint8 +} + +func (c *PtrCode) Kind() CodeKind { + return CodeKindPtr +} + +func (c *PtrCode) ToOpcode(ctx *compileContext) Opcodes { + codes := c.value.ToOpcode(ctx) + codes.First().Op = convertPtrOp(codes.First()) + codes.First().PtrNum = c.ptrNum + return codes +} + +func (c *PtrCode) ToAnonymousOpcode(ctx *compileContext) Opcodes { + var codes Opcodes + anonymCode, ok := c.value.(AnonymousCode) + if ok { + codes = anonymCode.ToAnonymousOpcode(ctx) + } else { + codes = c.value.ToOpcode(ctx) + } + codes.First().Op = convertPtrOp(codes.First()) + codes.First().PtrNum = c.ptrNum + return codes +} + +func (c *PtrCode) Filter(query *FieldQuery) Code { + return &PtrCode{ + typ: c.typ, + value: c.value.Filter(query), + ptrNum: c.ptrNum, + } +} + +func convertPtrOp(code *Opcode) OpType { + ptrHeadOp := code.Op.HeadToPtrHead() + if code.Op != ptrHeadOp { + if code.PtrNum > 0 { + // ptr field and ptr head + code.PtrNum-- + } + return ptrHeadOp + } + switch code.Op { + case OpInt: + return OpIntPtr + case OpUint: + return OpUintPtr + case OpFloat32: + return OpFloat32Ptr + case OpFloat64: + return OpFloat64Ptr + case OpString: + return OpStringPtr + case OpBool: + return OpBoolPtr + case OpBytes: + return OpBytesPtr + case OpNumber: + return OpNumberPtr + case OpArray: + return OpArrayPtr + case OpSlice: + return OpSlicePtr + case OpMap: + return OpMapPtr + case OpMarshalJSON: + return OpMarshalJSONPtr + case OpMarshalText: + return OpMarshalTextPtr + case OpInterface: + return OpInterfacePtr + case OpRecursive: + return OpRecursivePtr + } + return code.Op +} + +func isEmbeddedStruct(field *StructFieldCode) bool { + if !field.isAnonymous { + return false + } + t := field.typ + if t.Kind() == reflect.Ptr { + t = t.Elem() + } + return t.Kind() == reflect.Struct +} diff --git a/vendor/github.com/goccy/go-json/internal/encoder/compact.go b/vendor/github.com/goccy/go-json/internal/encoder/compact.go new file mode 100644 index 000000000..0eb9545d8 --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/encoder/compact.go @@ -0,0 +1,286 @@ +package encoder + +import ( + "bytes" + "fmt" + "strconv" + "unsafe" + + "github.com/goccy/go-json/internal/errors" +) + +var ( + isWhiteSpace = [256]bool{ + ' ': true, + '\n': true, + '\t': true, + '\r': true, + } + isHTMLEscapeChar = [256]bool{ + '<': true, + '>': true, + '&': true, + } + nul = byte('\000') +) + +func Compact(buf *bytes.Buffer, src []byte, escape bool) error { + if len(src) == 0 { + return errors.ErrUnexpectedEndOfJSON("", 0) + } + buf.Grow(len(src)) + dst := buf.Bytes() + + ctx := TakeRuntimeContext() + ctxBuf := ctx.Buf[:0] + ctxBuf = append(append(ctxBuf, src...), nul) + ctx.Buf = ctxBuf + + if err := compactAndWrite(buf, dst, ctxBuf, escape); err != nil { + ReleaseRuntimeContext(ctx) + return err + } + ReleaseRuntimeContext(ctx) + return nil +} + +func compactAndWrite(buf *bytes.Buffer, dst []byte, src []byte, escape bool) error { + dst, err := compact(dst, src, escape) + if err != nil { + return err + } + if _, err := buf.Write(dst); err != nil { + return err + } + return nil +} + +func compact(dst, src []byte, escape bool) ([]byte, error) { + buf, cursor, err := compactValue(dst, src, 0, escape) + if err != nil { + return nil, err + } + if err := validateEndBuf(src, cursor); err != nil { + return nil, err + } + return buf, nil +} + +func validateEndBuf(src []byte, cursor int64) error { + for { + switch src[cursor] { + case ' ', '\t', '\n', '\r': + cursor++ + continue + case nul: + return nil + } + return errors.ErrSyntax( + fmt.Sprintf("invalid character '%c' after top-level value", src[cursor]), + cursor+1, + ) + } +} + +func skipWhiteSpace(buf []byte, cursor int64) int64 { +LOOP: + if isWhiteSpace[buf[cursor]] { + cursor++ + goto LOOP + } + return cursor +} + +func compactValue(dst, src []byte, cursor int64, escape bool) ([]byte, int64, error) { + for { + switch src[cursor] { + case ' ', '\t', '\n', '\r': + cursor++ + continue + case '{': + return compactObject(dst, src, cursor, escape) + case '}': + return nil, 0, errors.ErrSyntax("unexpected character '}'", cursor) + case '[': + return compactArray(dst, src, cursor, escape) + case ']': + return nil, 0, errors.ErrSyntax("unexpected character ']'", cursor) + case '"': + return compactString(dst, src, cursor, escape) + case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + return compactNumber(dst, src, cursor) + case 't': + return compactTrue(dst, src, cursor) + case 'f': + return compactFalse(dst, src, cursor) + case 'n': + return compactNull(dst, src, cursor) + default: + return nil, 0, errors.ErrSyntax(fmt.Sprintf("unexpected character '%c'", src[cursor]), cursor) + } + } +} + +func compactObject(dst, src []byte, cursor int64, escape bool) ([]byte, int64, error) { + if src[cursor] == '{' { + dst = append(dst, '{') + } else { + return nil, 0, errors.ErrExpected("expected { character for object value", cursor) + } + cursor = skipWhiteSpace(src, cursor+1) + if src[cursor] == '}' { + dst = append(dst, '}') + return dst, cursor + 1, nil + } + var err error + for { + cursor = skipWhiteSpace(src, cursor) + dst, cursor, err = compactString(dst, src, cursor, escape) + if err != nil { + return nil, 0, err + } + cursor = skipWhiteSpace(src, cursor) + if src[cursor] != ':' { + return nil, 0, errors.ErrExpected("colon after object key", cursor) + } + dst = append(dst, ':') + dst, cursor, err = compactValue(dst, src, cursor+1, escape) + if err != nil { + return nil, 0, err + } + cursor = skipWhiteSpace(src, cursor) + switch src[cursor] { + case '}': + dst = append(dst, '}') + cursor++ + return dst, cursor, nil + case ',': + dst = append(dst, ',') + default: + return nil, 0, errors.ErrExpected("comma after object value", cursor) + } + cursor++ + } +} + +func compactArray(dst, src []byte, cursor int64, escape bool) ([]byte, int64, error) { + if src[cursor] == '[' { + dst = append(dst, '[') + } else { + return nil, 0, errors.ErrExpected("expected [ character for array value", cursor) + } + cursor = skipWhiteSpace(src, cursor+1) + if src[cursor] == ']' { + dst = append(dst, ']') + return dst, cursor + 1, nil + } + var err error + for { + dst, cursor, err = compactValue(dst, src, cursor, escape) + if err != nil { + return nil, 0, err + } + cursor = skipWhiteSpace(src, cursor) + switch src[cursor] { + case ']': + dst = append(dst, ']') + cursor++ + return dst, cursor, nil + case ',': + dst = append(dst, ',') + default: + return nil, 0, errors.ErrExpected("comma after array value", cursor) + } + cursor++ + } +} + +func compactString(dst, src []byte, cursor int64, escape bool) ([]byte, int64, error) { + if src[cursor] != '"' { + return nil, 0, errors.ErrInvalidCharacter(src[cursor], "string", cursor) + } + start := cursor + for { + cursor++ + c := src[cursor] + if escape { + if isHTMLEscapeChar[c] { + dst = append(dst, src[start:cursor]...) + dst = append(dst, `\u00`...) + dst = append(dst, hex[c>>4], hex[c&0xF]) + start = cursor + 1 + } else if c == 0xE2 && cursor+2 < int64(len(src)) && src[cursor+1] == 0x80 && src[cursor+2]&^1 == 0xA8 { + dst = append(dst, src[start:cursor]...) + dst = append(dst, `\u202`...) + dst = append(dst, hex[src[cursor+2]&0xF]) + cursor += 2 + start = cursor + 3 + } + } + switch c { + case '\\': + cursor++ + if src[cursor] == nul { + return nil, 0, errors.ErrUnexpectedEndOfJSON("string", int64(len(src))) + } + case '"': + cursor++ + return append(dst, src[start:cursor]...), cursor, nil + case nul: + return nil, 0, errors.ErrUnexpectedEndOfJSON("string", int64(len(src))) + } + } +} + +func compactNumber(dst, src []byte, cursor int64) ([]byte, int64, error) { + start := cursor + for { + cursor++ + if floatTable[src[cursor]] { + continue + } + break + } + num := src[start:cursor] + if _, err := strconv.ParseFloat(*(*string)(unsafe.Pointer(&num)), 64); err != nil { + return nil, 0, err + } + dst = append(dst, num...) + return dst, cursor, nil +} + +func compactTrue(dst, src []byte, cursor int64) ([]byte, int64, error) { + if cursor+3 >= int64(len(src)) { + return nil, 0, errors.ErrUnexpectedEndOfJSON("true", cursor) + } + if !bytes.Equal(src[cursor:cursor+4], []byte(`true`)) { + return nil, 0, errors.ErrInvalidCharacter(src[cursor], "true", cursor) + } + dst = append(dst, "true"...) + cursor += 4 + return dst, cursor, nil +} + +func compactFalse(dst, src []byte, cursor int64) ([]byte, int64, error) { + if cursor+4 >= int64(len(src)) { + return nil, 0, errors.ErrUnexpectedEndOfJSON("false", cursor) + } + if !bytes.Equal(src[cursor:cursor+5], []byte(`false`)) { + return nil, 0, errors.ErrInvalidCharacter(src[cursor], "false", cursor) + } + dst = append(dst, "false"...) + cursor += 5 + return dst, cursor, nil +} + +func compactNull(dst, src []byte, cursor int64) ([]byte, int64, error) { + if cursor+3 >= int64(len(src)) { + return nil, 0, errors.ErrUnexpectedEndOfJSON("null", cursor) + } + if !bytes.Equal(src[cursor:cursor+4], []byte(`null`)) { + return nil, 0, errors.ErrInvalidCharacter(src[cursor], "null", cursor) + } + dst = append(dst, "null"...) + cursor += 4 + return dst, cursor, nil +} diff --git a/vendor/github.com/goccy/go-json/internal/encoder/compiler.go b/vendor/github.com/goccy/go-json/internal/encoder/compiler.go new file mode 100644 index 000000000..3ae39ba8c --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/encoder/compiler.go @@ -0,0 +1,935 @@ +package encoder + +import ( + "context" + "encoding" + "encoding/json" + "reflect" + "sync/atomic" + "unsafe" + + "github.com/goccy/go-json/internal/errors" + "github.com/goccy/go-json/internal/runtime" +) + +type marshalerContext interface { + MarshalJSON(context.Context) ([]byte, error) +} + +var ( + marshalJSONType = reflect.TypeOf((*json.Marshaler)(nil)).Elem() + marshalJSONContextType = reflect.TypeOf((*marshalerContext)(nil)).Elem() + marshalTextType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem() + jsonNumberType = reflect.TypeOf(json.Number("")) + cachedOpcodeSets []*OpcodeSet + cachedOpcodeMap unsafe.Pointer // map[uintptr]*OpcodeSet + typeAddr *runtime.TypeAddr +) + +func init() { + typeAddr = runtime.AnalyzeTypeAddr() + if typeAddr == nil { + typeAddr = &runtime.TypeAddr{} + } + cachedOpcodeSets = make([]*OpcodeSet, typeAddr.AddrRange>>typeAddr.AddrShift+1) +} + +func loadOpcodeMap() map[uintptr]*OpcodeSet { + p := atomic.LoadPointer(&cachedOpcodeMap) + return *(*map[uintptr]*OpcodeSet)(unsafe.Pointer(&p)) +} + +func storeOpcodeSet(typ uintptr, set *OpcodeSet, m map[uintptr]*OpcodeSet) { + newOpcodeMap := make(map[uintptr]*OpcodeSet, len(m)+1) + newOpcodeMap[typ] = set + + for k, v := range m { + newOpcodeMap[k] = v + } + + atomic.StorePointer(&cachedOpcodeMap, *(*unsafe.Pointer)(unsafe.Pointer(&newOpcodeMap))) +} + +func compileToGetCodeSetSlowPath(typeptr uintptr) (*OpcodeSet, error) { + opcodeMap := loadOpcodeMap() + if codeSet, exists := opcodeMap[typeptr]; exists { + return codeSet, nil + } + codeSet, err := newCompiler().compile(typeptr) + if err != nil { + return nil, err + } + storeOpcodeSet(typeptr, codeSet, opcodeMap) + return codeSet, nil +} + +func getFilteredCodeSetIfNeeded(ctx *RuntimeContext, codeSet *OpcodeSet) (*OpcodeSet, error) { + if (ctx.Option.Flag & ContextOption) == 0 { + return codeSet, nil + } + query := FieldQueryFromContext(ctx.Option.Context) + if query == nil { + return codeSet, nil + } + ctx.Option.Flag |= FieldQueryOption + cacheCodeSet := codeSet.getQueryCache(query.Hash()) + if cacheCodeSet != nil { + return cacheCodeSet, nil + } + queryCodeSet, err := newCompiler().codeToOpcodeSet(codeSet.Type, codeSet.Code.Filter(query)) + if err != nil { + return nil, err + } + codeSet.setQueryCache(query.Hash(), queryCodeSet) + return queryCodeSet, nil +} + +type Compiler struct { + structTypeToCode map[uintptr]*StructCode +} + +func newCompiler() *Compiler { + return &Compiler{ + structTypeToCode: map[uintptr]*StructCode{}, + } +} + +func (c *Compiler) compile(typeptr uintptr) (*OpcodeSet, error) { + // noescape trick for header.typ ( reflect.*rtype ) + typ := *(**runtime.Type)(unsafe.Pointer(&typeptr)) + code, err := c.typeToCode(typ) + if err != nil { + return nil, err + } + return c.codeToOpcodeSet(typ, code) +} + +func (c *Compiler) codeToOpcodeSet(typ *runtime.Type, code Code) (*OpcodeSet, error) { + noescapeKeyCode := c.codeToOpcode(&compileContext{ + structTypeToCodes: map[uintptr]Opcodes{}, + recursiveCodes: &Opcodes{}, + }, typ, code) + if err := noescapeKeyCode.Validate(); err != nil { + return nil, err + } + escapeKeyCode := c.codeToOpcode(&compileContext{ + structTypeToCodes: map[uintptr]Opcodes{}, + recursiveCodes: &Opcodes{}, + escapeKey: true, + }, typ, code) + noescapeKeyCode = copyOpcode(noescapeKeyCode) + escapeKeyCode = copyOpcode(escapeKeyCode) + setTotalLengthToInterfaceOp(noescapeKeyCode) + setTotalLengthToInterfaceOp(escapeKeyCode) + interfaceNoescapeKeyCode := copyToInterfaceOpcode(noescapeKeyCode) + interfaceEscapeKeyCode := copyToInterfaceOpcode(escapeKeyCode) + codeLength := noescapeKeyCode.TotalLength() + return &OpcodeSet{ + Type: typ, + NoescapeKeyCode: noescapeKeyCode, + EscapeKeyCode: escapeKeyCode, + InterfaceNoescapeKeyCode: interfaceNoescapeKeyCode, + InterfaceEscapeKeyCode: interfaceEscapeKeyCode, + CodeLength: codeLength, + EndCode: ToEndCode(interfaceNoescapeKeyCode), + Code: code, + QueryCache: map[string]*OpcodeSet{}, + }, nil +} + +func (c *Compiler) typeToCode(typ *runtime.Type) (Code, error) { + switch { + case c.implementsMarshalJSON(typ): + return c.marshalJSONCode(typ) + case c.implementsMarshalText(typ): + return c.marshalTextCode(typ) + } + + isPtr := false + orgType := typ + if typ.Kind() == reflect.Ptr { + typ = typ.Elem() + isPtr = true + } + switch { + case c.implementsMarshalJSON(typ): + return c.marshalJSONCode(orgType) + case c.implementsMarshalText(typ): + return c.marshalTextCode(orgType) + } + switch typ.Kind() { + case reflect.Slice: + elem := typ.Elem() + if elem.Kind() == reflect.Uint8 { + p := runtime.PtrTo(elem) + if !c.implementsMarshalJSONType(p) && !p.Implements(marshalTextType) { + return c.bytesCode(typ, isPtr) + } + } + return c.sliceCode(typ) + case reflect.Map: + if isPtr { + return c.ptrCode(runtime.PtrTo(typ)) + } + return c.mapCode(typ) + case reflect.Struct: + return c.structCode(typ, isPtr) + case reflect.Int: + return c.intCode(typ, isPtr) + case reflect.Int8: + return c.int8Code(typ, isPtr) + case reflect.Int16: + return c.int16Code(typ, isPtr) + case reflect.Int32: + return c.int32Code(typ, isPtr) + case reflect.Int64: + return c.int64Code(typ, isPtr) + case reflect.Uint, reflect.Uintptr: + return c.uintCode(typ, isPtr) + case reflect.Uint8: + return c.uint8Code(typ, isPtr) + case reflect.Uint16: + return c.uint16Code(typ, isPtr) + case reflect.Uint32: + return c.uint32Code(typ, isPtr) + case reflect.Uint64: + return c.uint64Code(typ, isPtr) + case reflect.Float32: + return c.float32Code(typ, isPtr) + case reflect.Float64: + return c.float64Code(typ, isPtr) + case reflect.String: + return c.stringCode(typ, isPtr) + case reflect.Bool: + return c.boolCode(typ, isPtr) + case reflect.Interface: + return c.interfaceCode(typ, isPtr) + default: + if isPtr && typ.Implements(marshalTextType) { + typ = orgType + } + return c.typeToCodeWithPtr(typ, isPtr) + } +} + +func (c *Compiler) typeToCodeWithPtr(typ *runtime.Type, isPtr bool) (Code, error) { + switch { + case c.implementsMarshalJSON(typ): + return c.marshalJSONCode(typ) + case c.implementsMarshalText(typ): + return c.marshalTextCode(typ) + } + switch typ.Kind() { + case reflect.Ptr: + return c.ptrCode(typ) + case reflect.Slice: + elem := typ.Elem() + if elem.Kind() == reflect.Uint8 { + p := runtime.PtrTo(elem) + if !c.implementsMarshalJSONType(p) && !p.Implements(marshalTextType) { + return c.bytesCode(typ, false) + } + } + return c.sliceCode(typ) + case reflect.Array: + return c.arrayCode(typ) + case reflect.Map: + return c.mapCode(typ) + case reflect.Struct: + return c.structCode(typ, isPtr) + case reflect.Interface: + return c.interfaceCode(typ, false) + case reflect.Int: + return c.intCode(typ, false) + case reflect.Int8: + return c.int8Code(typ, false) + case reflect.Int16: + return c.int16Code(typ, false) + case reflect.Int32: + return c.int32Code(typ, false) + case reflect.Int64: + return c.int64Code(typ, false) + case reflect.Uint: + return c.uintCode(typ, false) + case reflect.Uint8: + return c.uint8Code(typ, false) + case reflect.Uint16: + return c.uint16Code(typ, false) + case reflect.Uint32: + return c.uint32Code(typ, false) + case reflect.Uint64: + return c.uint64Code(typ, false) + case reflect.Uintptr: + return c.uintCode(typ, false) + case reflect.Float32: + return c.float32Code(typ, false) + case reflect.Float64: + return c.float64Code(typ, false) + case reflect.String: + return c.stringCode(typ, false) + case reflect.Bool: + return c.boolCode(typ, false) + } + return nil, &errors.UnsupportedTypeError{Type: runtime.RType2Type(typ)} +} + +const intSize = 32 << (^uint(0) >> 63) + +//nolint:unparam +func (c *Compiler) intCode(typ *runtime.Type, isPtr bool) (*IntCode, error) { + return &IntCode{typ: typ, bitSize: intSize, isPtr: isPtr}, nil +} + +//nolint:unparam +func (c *Compiler) int8Code(typ *runtime.Type, isPtr bool) (*IntCode, error) { + return &IntCode{typ: typ, bitSize: 8, isPtr: isPtr}, nil +} + +//nolint:unparam +func (c *Compiler) int16Code(typ *runtime.Type, isPtr bool) (*IntCode, error) { + return &IntCode{typ: typ, bitSize: 16, isPtr: isPtr}, nil +} + +//nolint:unparam +func (c *Compiler) int32Code(typ *runtime.Type, isPtr bool) (*IntCode, error) { + return &IntCode{typ: typ, bitSize: 32, isPtr: isPtr}, nil +} + +//nolint:unparam +func (c *Compiler) int64Code(typ *runtime.Type, isPtr bool) (*IntCode, error) { + return &IntCode{typ: typ, bitSize: 64, isPtr: isPtr}, nil +} + +//nolint:unparam +func (c *Compiler) uintCode(typ *runtime.Type, isPtr bool) (*UintCode, error) { + return &UintCode{typ: typ, bitSize: intSize, isPtr: isPtr}, nil +} + +//nolint:unparam +func (c *Compiler) uint8Code(typ *runtime.Type, isPtr bool) (*UintCode, error) { + return &UintCode{typ: typ, bitSize: 8, isPtr: isPtr}, nil +} + +//nolint:unparam +func (c *Compiler) uint16Code(typ *runtime.Type, isPtr bool) (*UintCode, error) { + return &UintCode{typ: typ, bitSize: 16, isPtr: isPtr}, nil +} + +//nolint:unparam +func (c *Compiler) uint32Code(typ *runtime.Type, isPtr bool) (*UintCode, error) { + return &UintCode{typ: typ, bitSize: 32, isPtr: isPtr}, nil +} + +//nolint:unparam +func (c *Compiler) uint64Code(typ *runtime.Type, isPtr bool) (*UintCode, error) { + return &UintCode{typ: typ, bitSize: 64, isPtr: isPtr}, nil +} + +//nolint:unparam +func (c *Compiler) float32Code(typ *runtime.Type, isPtr bool) (*FloatCode, error) { + return &FloatCode{typ: typ, bitSize: 32, isPtr: isPtr}, nil +} + +//nolint:unparam +func (c *Compiler) float64Code(typ *runtime.Type, isPtr bool) (*FloatCode, error) { + return &FloatCode{typ: typ, bitSize: 64, isPtr: isPtr}, nil +} + +//nolint:unparam +func (c *Compiler) stringCode(typ *runtime.Type, isPtr bool) (*StringCode, error) { + return &StringCode{typ: typ, isPtr: isPtr}, nil +} + +//nolint:unparam +func (c *Compiler) boolCode(typ *runtime.Type, isPtr bool) (*BoolCode, error) { + return &BoolCode{typ: typ, isPtr: isPtr}, nil +} + +//nolint:unparam +func (c *Compiler) intStringCode(typ *runtime.Type) (*IntCode, error) { + return &IntCode{typ: typ, bitSize: intSize, isString: true}, nil +} + +//nolint:unparam +func (c *Compiler) int8StringCode(typ *runtime.Type) (*IntCode, error) { + return &IntCode{typ: typ, bitSize: 8, isString: true}, nil +} + +//nolint:unparam +func (c *Compiler) int16StringCode(typ *runtime.Type) (*IntCode, error) { + return &IntCode{typ: typ, bitSize: 16, isString: true}, nil +} + +//nolint:unparam +func (c *Compiler) int32StringCode(typ *runtime.Type) (*IntCode, error) { + return &IntCode{typ: typ, bitSize: 32, isString: true}, nil +} + +//nolint:unparam +func (c *Compiler) int64StringCode(typ *runtime.Type) (*IntCode, error) { + return &IntCode{typ: typ, bitSize: 64, isString: true}, nil +} + +//nolint:unparam +func (c *Compiler) uintStringCode(typ *runtime.Type) (*UintCode, error) { + return &UintCode{typ: typ, bitSize: intSize, isString: true}, nil +} + +//nolint:unparam +func (c *Compiler) uint8StringCode(typ *runtime.Type) (*UintCode, error) { + return &UintCode{typ: typ, bitSize: 8, isString: true}, nil +} + +//nolint:unparam +func (c *Compiler) uint16StringCode(typ *runtime.Type) (*UintCode, error) { + return &UintCode{typ: typ, bitSize: 16, isString: true}, nil +} + +//nolint:unparam +func (c *Compiler) uint32StringCode(typ *runtime.Type) (*UintCode, error) { + return &UintCode{typ: typ, bitSize: 32, isString: true}, nil +} + +//nolint:unparam +func (c *Compiler) uint64StringCode(typ *runtime.Type) (*UintCode, error) { + return &UintCode{typ: typ, bitSize: 64, isString: true}, nil +} + +//nolint:unparam +func (c *Compiler) bytesCode(typ *runtime.Type, isPtr bool) (*BytesCode, error) { + return &BytesCode{typ: typ, isPtr: isPtr}, nil +} + +//nolint:unparam +func (c *Compiler) interfaceCode(typ *runtime.Type, isPtr bool) (*InterfaceCode, error) { + return &InterfaceCode{typ: typ, isPtr: isPtr}, nil +} + +//nolint:unparam +func (c *Compiler) marshalJSONCode(typ *runtime.Type) (*MarshalJSONCode, error) { + return &MarshalJSONCode{ + typ: typ, + isAddrForMarshaler: c.isPtrMarshalJSONType(typ), + isNilableType: c.isNilableType(typ), + isMarshalerContext: typ.Implements(marshalJSONContextType) || runtime.PtrTo(typ).Implements(marshalJSONContextType), + }, nil +} + +//nolint:unparam +func (c *Compiler) marshalTextCode(typ *runtime.Type) (*MarshalTextCode, error) { + return &MarshalTextCode{ + typ: typ, + isAddrForMarshaler: c.isPtrMarshalTextType(typ), + isNilableType: c.isNilableType(typ), + }, nil +} + +func (c *Compiler) ptrCode(typ *runtime.Type) (*PtrCode, error) { + code, err := c.typeToCodeWithPtr(typ.Elem(), true) + if err != nil { + return nil, err + } + ptr, ok := code.(*PtrCode) + if ok { + return &PtrCode{typ: typ, value: ptr.value, ptrNum: ptr.ptrNum + 1}, nil + } + return &PtrCode{typ: typ, value: code, ptrNum: 1}, nil +} + +func (c *Compiler) sliceCode(typ *runtime.Type) (*SliceCode, error) { + elem := typ.Elem() + code, err := c.listElemCode(elem) + if err != nil { + return nil, err + } + if code.Kind() == CodeKindStruct { + structCode := code.(*StructCode) + structCode.enableIndirect() + } + return &SliceCode{typ: typ, value: code}, nil +} + +func (c *Compiler) arrayCode(typ *runtime.Type) (*ArrayCode, error) { + elem := typ.Elem() + code, err := c.listElemCode(elem) + if err != nil { + return nil, err + } + if code.Kind() == CodeKindStruct { + structCode := code.(*StructCode) + structCode.enableIndirect() + } + return &ArrayCode{typ: typ, value: code}, nil +} + +func (c *Compiler) mapCode(typ *runtime.Type) (*MapCode, error) { + keyCode, err := c.mapKeyCode(typ.Key()) + if err != nil { + return nil, err + } + valueCode, err := c.mapValueCode(typ.Elem()) + if err != nil { + return nil, err + } + if valueCode.Kind() == CodeKindStruct { + structCode := valueCode.(*StructCode) + structCode.enableIndirect() + } + return &MapCode{typ: typ, key: keyCode, value: valueCode}, nil +} + +func (c *Compiler) listElemCode(typ *runtime.Type) (Code, error) { + switch { + case c.isPtrMarshalJSONType(typ): + return c.marshalJSONCode(typ) + case !typ.Implements(marshalTextType) && runtime.PtrTo(typ).Implements(marshalTextType): + return c.marshalTextCode(typ) + case typ.Kind() == reflect.Map: + return c.ptrCode(runtime.PtrTo(typ)) + default: + // isPtr was originally used to indicate whether the type of top level is pointer. + // However, since the slice/array element is a specification that can get the pointer address, explicitly set isPtr to true. + // See here for related issues: https://github.com/goccy/go-json/issues/370 + code, err := c.typeToCodeWithPtr(typ, true) + if err != nil { + return nil, err + } + ptr, ok := code.(*PtrCode) + if ok { + if ptr.value.Kind() == CodeKindMap { + ptr.ptrNum++ + } + } + return code, nil + } +} + +func (c *Compiler) mapKeyCode(typ *runtime.Type) (Code, error) { + switch { + case c.implementsMarshalText(typ): + return c.marshalTextCode(typ) + } + switch typ.Kind() { + case reflect.Ptr: + return c.ptrCode(typ) + case reflect.String: + return c.stringCode(typ, false) + case reflect.Int: + return c.intStringCode(typ) + case reflect.Int8: + return c.int8StringCode(typ) + case reflect.Int16: + return c.int16StringCode(typ) + case reflect.Int32: + return c.int32StringCode(typ) + case reflect.Int64: + return c.int64StringCode(typ) + case reflect.Uint: + return c.uintStringCode(typ) + case reflect.Uint8: + return c.uint8StringCode(typ) + case reflect.Uint16: + return c.uint16StringCode(typ) + case reflect.Uint32: + return c.uint32StringCode(typ) + case reflect.Uint64: + return c.uint64StringCode(typ) + case reflect.Uintptr: + return c.uintStringCode(typ) + } + return nil, &errors.UnsupportedTypeError{Type: runtime.RType2Type(typ)} +} + +func (c *Compiler) mapValueCode(typ *runtime.Type) (Code, error) { + switch typ.Kind() { + case reflect.Map: + return c.ptrCode(runtime.PtrTo(typ)) + default: + code, err := c.typeToCodeWithPtr(typ, false) + if err != nil { + return nil, err + } + ptr, ok := code.(*PtrCode) + if ok { + if ptr.value.Kind() == CodeKindMap { + ptr.ptrNum++ + } + } + return code, nil + } +} + +func (c *Compiler) structCode(typ *runtime.Type, isPtr bool) (*StructCode, error) { + typeptr := uintptr(unsafe.Pointer(typ)) + if code, exists := c.structTypeToCode[typeptr]; exists { + derefCode := *code + derefCode.isRecursive = true + return &derefCode, nil + } + indirect := runtime.IfaceIndir(typ) + code := &StructCode{typ: typ, isPtr: isPtr, isIndirect: indirect} + c.structTypeToCode[typeptr] = code + + fieldNum := typ.NumField() + tags := c.typeToStructTags(typ) + fields := []*StructFieldCode{} + for i, tag := range tags { + isOnlyOneFirstField := i == 0 && fieldNum == 1 + field, err := c.structFieldCode(code, tag, isPtr, isOnlyOneFirstField) + if err != nil { + return nil, err + } + if field.isAnonymous { + structCode := field.getAnonymousStruct() + if structCode != nil { + structCode.removeFieldsByTags(tags) + if c.isAssignableIndirect(field, isPtr) { + if indirect { + structCode.isIndirect = true + } else { + structCode.isIndirect = false + } + } + } + } else { + structCode := field.getStruct() + if structCode != nil { + if indirect { + // if parent is indirect type, set child indirect property to true + structCode.isIndirect = true + } else { + // if parent is not indirect type, set child indirect property to false. + // but if parent's indirect is false and isPtr is true, then indirect must be true. + // Do this only if indirectConversion is enabled at the end of compileStruct. + structCode.isIndirect = false + } + } + } + fields = append(fields, field) + } + fieldMap := c.getFieldMap(fields) + duplicatedFieldMap := c.getDuplicatedFieldMap(fieldMap) + code.fields = c.filteredDuplicatedFields(fields, duplicatedFieldMap) + if !code.disableIndirectConversion && !indirect && isPtr { + code.enableIndirect() + } + delete(c.structTypeToCode, typeptr) + return code, nil +} + +func toElemType(t *runtime.Type) *runtime.Type { + for t.Kind() == reflect.Ptr { + t = t.Elem() + } + return t +} + +func (c *Compiler) structFieldCode(structCode *StructCode, tag *runtime.StructTag, isPtr, isOnlyOneFirstField bool) (*StructFieldCode, error) { + field := tag.Field + fieldType := runtime.Type2RType(field.Type) + isIndirectSpecialCase := isPtr && isOnlyOneFirstField + fieldCode := &StructFieldCode{ + typ: fieldType, + key: tag.Key, + tag: tag, + offset: field.Offset, + isAnonymous: field.Anonymous && !tag.IsTaggedKey && toElemType(fieldType).Kind() == reflect.Struct, + isTaggedKey: tag.IsTaggedKey, + isNilableType: c.isNilableType(fieldType), + isNilCheck: true, + } + switch { + case c.isMovePointerPositionFromHeadToFirstMarshalJSONFieldCase(fieldType, isIndirectSpecialCase): + code, err := c.marshalJSONCode(fieldType) + if err != nil { + return nil, err + } + fieldCode.value = code + fieldCode.isAddrForMarshaler = true + fieldCode.isNilCheck = false + structCode.isIndirect = false + structCode.disableIndirectConversion = true + case c.isMovePointerPositionFromHeadToFirstMarshalTextFieldCase(fieldType, isIndirectSpecialCase): + code, err := c.marshalTextCode(fieldType) + if err != nil { + return nil, err + } + fieldCode.value = code + fieldCode.isAddrForMarshaler = true + fieldCode.isNilCheck = false + structCode.isIndirect = false + structCode.disableIndirectConversion = true + case isPtr && c.isPtrMarshalJSONType(fieldType): + // *struct{ field T } + // func (*T) MarshalJSON() ([]byte, error) + code, err := c.marshalJSONCode(fieldType) + if err != nil { + return nil, err + } + fieldCode.value = code + fieldCode.isAddrForMarshaler = true + fieldCode.isNilCheck = false + case isPtr && c.isPtrMarshalTextType(fieldType): + // *struct{ field T } + // func (*T) MarshalText() ([]byte, error) + code, err := c.marshalTextCode(fieldType) + if err != nil { + return nil, err + } + fieldCode.value = code + fieldCode.isAddrForMarshaler = true + fieldCode.isNilCheck = false + default: + code, err := c.typeToCodeWithPtr(fieldType, isPtr) + if err != nil { + return nil, err + } + switch code.Kind() { + case CodeKindPtr, CodeKindInterface: + fieldCode.isNextOpPtrType = true + } + fieldCode.value = code + } + return fieldCode, nil +} + +func (c *Compiler) isAssignableIndirect(fieldCode *StructFieldCode, isPtr bool) bool { + if isPtr { + return false + } + codeType := fieldCode.value.Kind() + if codeType == CodeKindMarshalJSON { + return false + } + if codeType == CodeKindMarshalText { + return false + } + return true +} + +func (c *Compiler) getFieldMap(fields []*StructFieldCode) map[string][]*StructFieldCode { + fieldMap := map[string][]*StructFieldCode{} + for _, field := range fields { + if field.isAnonymous { + for k, v := range c.getAnonymousFieldMap(field) { + fieldMap[k] = append(fieldMap[k], v...) + } + continue + } + fieldMap[field.key] = append(fieldMap[field.key], field) + } + return fieldMap +} + +func (c *Compiler) getAnonymousFieldMap(field *StructFieldCode) map[string][]*StructFieldCode { + fieldMap := map[string][]*StructFieldCode{} + structCode := field.getAnonymousStruct() + if structCode == nil || structCode.isRecursive { + fieldMap[field.key] = append(fieldMap[field.key], field) + return fieldMap + } + for k, v := range c.getFieldMapFromAnonymousParent(structCode.fields) { + fieldMap[k] = append(fieldMap[k], v...) + } + return fieldMap +} + +func (c *Compiler) getFieldMapFromAnonymousParent(fields []*StructFieldCode) map[string][]*StructFieldCode { + fieldMap := map[string][]*StructFieldCode{} + for _, field := range fields { + if field.isAnonymous { + for k, v := range c.getAnonymousFieldMap(field) { + // Do not handle tagged key when embedding more than once + for _, vv := range v { + vv.isTaggedKey = false + } + fieldMap[k] = append(fieldMap[k], v...) + } + continue + } + fieldMap[field.key] = append(fieldMap[field.key], field) + } + return fieldMap +} + +func (c *Compiler) getDuplicatedFieldMap(fieldMap map[string][]*StructFieldCode) map[*StructFieldCode]struct{} { + duplicatedFieldMap := map[*StructFieldCode]struct{}{} + for _, fields := range fieldMap { + if len(fields) == 1 { + continue + } + if c.isTaggedKeyOnly(fields) { + for _, field := range fields { + if field.isTaggedKey { + continue + } + duplicatedFieldMap[field] = struct{}{} + } + } else { + for _, field := range fields { + duplicatedFieldMap[field] = struct{}{} + } + } + } + return duplicatedFieldMap +} + +func (c *Compiler) filteredDuplicatedFields(fields []*StructFieldCode, duplicatedFieldMap map[*StructFieldCode]struct{}) []*StructFieldCode { + filteredFields := make([]*StructFieldCode, 0, len(fields)) + for _, field := range fields { + if field.isAnonymous { + structCode := field.getAnonymousStruct() + if structCode != nil && !structCode.isRecursive { + structCode.fields = c.filteredDuplicatedFields(structCode.fields, duplicatedFieldMap) + if len(structCode.fields) > 0 { + filteredFields = append(filteredFields, field) + } + continue + } + } + if _, exists := duplicatedFieldMap[field]; exists { + continue + } + filteredFields = append(filteredFields, field) + } + return filteredFields +} + +func (c *Compiler) isTaggedKeyOnly(fields []*StructFieldCode) bool { + var taggedKeyFieldCount int + for _, field := range fields { + if field.isTaggedKey { + taggedKeyFieldCount++ + } + } + return taggedKeyFieldCount == 1 +} + +func (c *Compiler) typeToStructTags(typ *runtime.Type) runtime.StructTags { + tags := runtime.StructTags{} + fieldNum := typ.NumField() + for i := 0; i < fieldNum; i++ { + field := typ.Field(i) + if runtime.IsIgnoredStructField(field) { + continue + } + tags = append(tags, runtime.StructTagFromField(field)) + } + return tags +} + +// *struct{ field T } => struct { field *T } +// func (*T) MarshalJSON() ([]byte, error) +func (c *Compiler) isMovePointerPositionFromHeadToFirstMarshalJSONFieldCase(typ *runtime.Type, isIndirectSpecialCase bool) bool { + return isIndirectSpecialCase && !c.isNilableType(typ) && c.isPtrMarshalJSONType(typ) +} + +// *struct{ field T } => struct { field *T } +// func (*T) MarshalText() ([]byte, error) +func (c *Compiler) isMovePointerPositionFromHeadToFirstMarshalTextFieldCase(typ *runtime.Type, isIndirectSpecialCase bool) bool { + return isIndirectSpecialCase && !c.isNilableType(typ) && c.isPtrMarshalTextType(typ) +} + +func (c *Compiler) implementsMarshalJSON(typ *runtime.Type) bool { + if !c.implementsMarshalJSONType(typ) { + return false + } + if typ.Kind() != reflect.Ptr { + return true + } + // type kind is reflect.Ptr + if !c.implementsMarshalJSONType(typ.Elem()) { + return true + } + // needs to dereference + return false +} + +func (c *Compiler) implementsMarshalText(typ *runtime.Type) bool { + if !typ.Implements(marshalTextType) { + return false + } + if typ.Kind() != reflect.Ptr { + return true + } + // type kind is reflect.Ptr + if !typ.Elem().Implements(marshalTextType) { + return true + } + // needs to dereference + return false +} + +func (c *Compiler) isNilableType(typ *runtime.Type) bool { + if !runtime.IfaceIndir(typ) { + return true + } + switch typ.Kind() { + case reflect.Ptr: + return true + case reflect.Map: + return true + case reflect.Func: + return true + default: + return false + } +} + +func (c *Compiler) implementsMarshalJSONType(typ *runtime.Type) bool { + return typ.Implements(marshalJSONType) || typ.Implements(marshalJSONContextType) +} + +func (c *Compiler) isPtrMarshalJSONType(typ *runtime.Type) bool { + return !c.implementsMarshalJSONType(typ) && c.implementsMarshalJSONType(runtime.PtrTo(typ)) +} + +func (c *Compiler) isPtrMarshalTextType(typ *runtime.Type) bool { + return !typ.Implements(marshalTextType) && runtime.PtrTo(typ).Implements(marshalTextType) +} + +func (c *Compiler) codeToOpcode(ctx *compileContext, typ *runtime.Type, code Code) *Opcode { + codes := code.ToOpcode(ctx) + codes.Last().Next = newEndOp(ctx, typ) + c.linkRecursiveCode(ctx) + return codes.First() +} + +func (c *Compiler) linkRecursiveCode(ctx *compileContext) { + recursiveCodes := map[uintptr]*CompiledCode{} + for _, recursive := range *ctx.recursiveCodes { + typeptr := uintptr(unsafe.Pointer(recursive.Type)) + codes := ctx.structTypeToCodes[typeptr] + if recursiveCode, ok := recursiveCodes[typeptr]; ok { + *recursive.Jmp = *recursiveCode + continue + } + + code := copyOpcode(codes.First()) + code.Op = code.Op.PtrHeadToHead() + lastCode := newEndOp(&compileContext{}, recursive.Type) + lastCode.Op = OpRecursiveEnd + + // OpRecursiveEnd must set before call TotalLength + code.End.Next = lastCode + + totalLength := code.TotalLength() + + // Idx, ElemIdx, Length must set after call TotalLength + lastCode.Idx = uint32((totalLength + 1) * uintptrSize) + lastCode.ElemIdx = lastCode.Idx + uintptrSize + lastCode.Length = lastCode.Idx + 2*uintptrSize + + // extend length to alloc slot for elemIdx + length + curTotalLength := uintptr(recursive.TotalLength()) + 3 + nextTotalLength := uintptr(totalLength) + 3 + + compiled := recursive.Jmp + compiled.Code = code + compiled.CurLen = curTotalLength + compiled.NextLen = nextTotalLength + compiled.Linked = true + + recursiveCodes[typeptr] = compiled + } +} diff --git a/vendor/github.com/goccy/go-json/internal/encoder/compiler_norace.go b/vendor/github.com/goccy/go-json/internal/encoder/compiler_norace.go new file mode 100644 index 000000000..20c93cbf7 --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/encoder/compiler_norace.go @@ -0,0 +1,32 @@ +//go:build !race +// +build !race + +package encoder + +func CompileToGetCodeSet(ctx *RuntimeContext, typeptr uintptr) (*OpcodeSet, error) { + if typeptr > typeAddr.MaxTypeAddr || typeptr < typeAddr.BaseTypeAddr { + codeSet, err := compileToGetCodeSetSlowPath(typeptr) + if err != nil { + return nil, err + } + return getFilteredCodeSetIfNeeded(ctx, codeSet) + } + index := (typeptr - typeAddr.BaseTypeAddr) >> typeAddr.AddrShift + if codeSet := cachedOpcodeSets[index]; codeSet != nil { + filtered, err := getFilteredCodeSetIfNeeded(ctx, codeSet) + if err != nil { + return nil, err + } + return filtered, nil + } + codeSet, err := newCompiler().compile(typeptr) + if err != nil { + return nil, err + } + filtered, err := getFilteredCodeSetIfNeeded(ctx, codeSet) + if err != nil { + return nil, err + } + cachedOpcodeSets[index] = codeSet + return filtered, nil +} diff --git a/vendor/github.com/goccy/go-json/internal/encoder/compiler_race.go b/vendor/github.com/goccy/go-json/internal/encoder/compiler_race.go new file mode 100644 index 000000000..13ba23fdf --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/encoder/compiler_race.go @@ -0,0 +1,45 @@ +//go:build race +// +build race + +package encoder + +import ( + "sync" +) + +var setsMu sync.RWMutex + +func CompileToGetCodeSet(ctx *RuntimeContext, typeptr uintptr) (*OpcodeSet, error) { + if typeptr > typeAddr.MaxTypeAddr || typeptr < typeAddr.BaseTypeAddr { + codeSet, err := compileToGetCodeSetSlowPath(typeptr) + if err != nil { + return nil, err + } + return getFilteredCodeSetIfNeeded(ctx, codeSet) + } + index := (typeptr - typeAddr.BaseTypeAddr) >> typeAddr.AddrShift + setsMu.RLock() + if codeSet := cachedOpcodeSets[index]; codeSet != nil { + filtered, err := getFilteredCodeSetIfNeeded(ctx, codeSet) + if err != nil { + setsMu.RUnlock() + return nil, err + } + setsMu.RUnlock() + return filtered, nil + } + setsMu.RUnlock() + + codeSet, err := newCompiler().compile(typeptr) + if err != nil { + return nil, err + } + filtered, err := getFilteredCodeSetIfNeeded(ctx, codeSet) + if err != nil { + return nil, err + } + setsMu.Lock() + cachedOpcodeSets[index] = codeSet + setsMu.Unlock() + return filtered, nil +} diff --git a/vendor/github.com/goccy/go-json/internal/encoder/context.go b/vendor/github.com/goccy/go-json/internal/encoder/context.go new file mode 100644 index 000000000..3833d0c86 --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/encoder/context.go @@ -0,0 +1,105 @@ +package encoder + +import ( + "context" + "sync" + "unsafe" + + "github.com/goccy/go-json/internal/runtime" +) + +type compileContext struct { + opcodeIndex uint32 + ptrIndex int + indent uint32 + escapeKey bool + structTypeToCodes map[uintptr]Opcodes + recursiveCodes *Opcodes +} + +func (c *compileContext) incIndent() { + c.indent++ +} + +func (c *compileContext) decIndent() { + c.indent-- +} + +func (c *compileContext) incIndex() { + c.incOpcodeIndex() + c.incPtrIndex() +} + +func (c *compileContext) decIndex() { + c.decOpcodeIndex() + c.decPtrIndex() +} + +func (c *compileContext) incOpcodeIndex() { + c.opcodeIndex++ +} + +func (c *compileContext) decOpcodeIndex() { + c.opcodeIndex-- +} + +func (c *compileContext) incPtrIndex() { + c.ptrIndex++ +} + +func (c *compileContext) decPtrIndex() { + c.ptrIndex-- +} + +const ( + bufSize = 1024 +) + +var ( + runtimeContextPool = sync.Pool{ + New: func() interface{} { + return &RuntimeContext{ + Buf: make([]byte, 0, bufSize), + Ptrs: make([]uintptr, 128), + KeepRefs: make([]unsafe.Pointer, 0, 8), + Option: &Option{}, + } + }, + } +) + +type RuntimeContext struct { + Context context.Context + Buf []byte + MarshalBuf []byte + Ptrs []uintptr + KeepRefs []unsafe.Pointer + SeenPtr []uintptr + BaseIndent uint32 + Prefix []byte + IndentStr []byte + Option *Option +} + +func (c *RuntimeContext) Init(p uintptr, codelen int) { + if len(c.Ptrs) < codelen { + c.Ptrs = make([]uintptr, codelen) + } + c.Ptrs[0] = p + c.KeepRefs = c.KeepRefs[:0] + c.SeenPtr = c.SeenPtr[:0] + c.BaseIndent = 0 +} + +func (c *RuntimeContext) Ptr() uintptr { + header := (*runtime.SliceHeader)(unsafe.Pointer(&c.Ptrs)) + return uintptr(header.Data) +} + +func TakeRuntimeContext() *RuntimeContext { + return runtimeContextPool.Get().(*RuntimeContext) +} + +func ReleaseRuntimeContext(ctx *RuntimeContext) { + runtimeContextPool.Put(ctx) +} diff --git a/vendor/github.com/goccy/go-json/internal/encoder/decode_rune.go b/vendor/github.com/goccy/go-json/internal/encoder/decode_rune.go new file mode 100644 index 000000000..35c959d48 --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/encoder/decode_rune.go @@ -0,0 +1,126 @@ +package encoder + +import "unicode/utf8" + +const ( + // The default lowest and highest continuation byte. + locb = 128 //0b10000000 + hicb = 191 //0b10111111 + + // These names of these constants are chosen to give nice alignment in the + // table below. The first nibble is an index into acceptRanges or F for + // special one-byte cases. The second nibble is the Rune length or the + // Status for the special one-byte case. + xx = 0xF1 // invalid: size 1 + as = 0xF0 // ASCII: size 1 + s1 = 0x02 // accept 0, size 2 + s2 = 0x13 // accept 1, size 3 + s3 = 0x03 // accept 0, size 3 + s4 = 0x23 // accept 2, size 3 + s5 = 0x34 // accept 3, size 4 + s6 = 0x04 // accept 0, size 4 + s7 = 0x44 // accept 4, size 4 +) + +// first is information about the first byte in a UTF-8 sequence. +var first = [256]uint8{ + // 1 2 3 4 5 6 7 8 9 A B C D E F + as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x00-0x0F + as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x10-0x1F + as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x20-0x2F + as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x30-0x3F + as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x40-0x4F + as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x50-0x5F + as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x60-0x6F + as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x70-0x7F + // 1 2 3 4 5 6 7 8 9 A B C D E F + xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0x80-0x8F + xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0x90-0x9F + xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0xA0-0xAF + xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0xB0-0xBF + xx, xx, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, // 0xC0-0xCF + s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, // 0xD0-0xDF + s2, s3, s3, s3, s3, s3, s3, s3, s3, s3, s3, s3, s3, s4, s3, s3, // 0xE0-0xEF + s5, s6, s6, s6, s7, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0xF0-0xFF +} + +const ( + lineSep = byte(168) //'\u2028' + paragraphSep = byte(169) //'\u2029' +) + +type decodeRuneState int + +const ( + validUTF8State decodeRuneState = iota + runeErrorState + lineSepState + paragraphSepState +) + +func decodeRuneInString(s string) (decodeRuneState, int) { + n := len(s) + s0 := s[0] + x := first[s0] + if x >= as { + // The following code simulates an additional check for x == xx and + // handling the ASCII and invalid cases accordingly. This mask-and-or + // approach prevents an additional branch. + mask := rune(x) << 31 >> 31 // Create 0x0000 or 0xFFFF. + if rune(s[0])&^mask|utf8.RuneError&mask == utf8.RuneError { + return runeErrorState, 1 + } + return validUTF8State, 1 + } + sz := int(x & 7) + if n < sz { + return runeErrorState, 1 + } + s1 := s[1] + switch x >> 4 { + case 0: + if s1 < locb || hicb < s1 { + return runeErrorState, 1 + } + case 1: + if s1 < 0xA0 || hicb < s1 { + return runeErrorState, 1 + } + case 2: + if s1 < locb || 0x9F < s1 { + return runeErrorState, 1 + } + case 3: + if s1 < 0x90 || hicb < s1 { + return runeErrorState, 1 + } + case 4: + if s1 < locb || 0x8F < s1 { + return runeErrorState, 1 + } + } + if sz <= 2 { + return validUTF8State, 2 + } + s2 := s[2] + if s2 < locb || hicb < s2 { + return runeErrorState, 1 + } + if sz <= 3 { + // separator character prefixes: [2]byte{226, 128} + if s0 == 226 && s1 == 128 { + switch s2 { + case lineSep: + return lineSepState, 3 + case paragraphSep: + return paragraphSepState, 3 + } + } + return validUTF8State, 3 + } + s3 := s[3] + if s3 < locb || hicb < s3 { + return runeErrorState, 1 + } + return validUTF8State, 4 +} diff --git a/vendor/github.com/goccy/go-json/internal/encoder/encoder.go b/vendor/github.com/goccy/go-json/internal/encoder/encoder.go new file mode 100644 index 000000000..14eb6a0d6 --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/encoder/encoder.go @@ -0,0 +1,596 @@ +package encoder + +import ( + "bytes" + "encoding" + "encoding/base64" + "encoding/json" + "fmt" + "math" + "reflect" + "strconv" + "strings" + "sync" + "unsafe" + + "github.com/goccy/go-json/internal/errors" + "github.com/goccy/go-json/internal/runtime" +) + +func (t OpType) IsMultipleOpHead() bool { + switch t { + case OpStructHead: + return true + case OpStructHeadSlice: + return true + case OpStructHeadArray: + return true + case OpStructHeadMap: + return true + case OpStructHeadStruct: + return true + case OpStructHeadOmitEmpty: + return true + case OpStructHeadOmitEmptySlice: + return true + case OpStructHeadOmitEmptyArray: + return true + case OpStructHeadOmitEmptyMap: + return true + case OpStructHeadOmitEmptyStruct: + return true + case OpStructHeadSlicePtr: + return true + case OpStructHeadOmitEmptySlicePtr: + return true + case OpStructHeadArrayPtr: + return true + case OpStructHeadOmitEmptyArrayPtr: + return true + case OpStructHeadMapPtr: + return true + case OpStructHeadOmitEmptyMapPtr: + return true + } + return false +} + +func (t OpType) IsMultipleOpField() bool { + switch t { + case OpStructField: + return true + case OpStructFieldSlice: + return true + case OpStructFieldArray: + return true + case OpStructFieldMap: + return true + case OpStructFieldStruct: + return true + case OpStructFieldOmitEmpty: + return true + case OpStructFieldOmitEmptySlice: + return true + case OpStructFieldOmitEmptyArray: + return true + case OpStructFieldOmitEmptyMap: + return true + case OpStructFieldOmitEmptyStruct: + return true + case OpStructFieldSlicePtr: + return true + case OpStructFieldOmitEmptySlicePtr: + return true + case OpStructFieldArrayPtr: + return true + case OpStructFieldOmitEmptyArrayPtr: + return true + case OpStructFieldMapPtr: + return true + case OpStructFieldOmitEmptyMapPtr: + return true + } + return false +} + +type OpcodeSet struct { + Type *runtime.Type + NoescapeKeyCode *Opcode + EscapeKeyCode *Opcode + InterfaceNoescapeKeyCode *Opcode + InterfaceEscapeKeyCode *Opcode + CodeLength int + EndCode *Opcode + Code Code + QueryCache map[string]*OpcodeSet + cacheMu sync.RWMutex +} + +func (s *OpcodeSet) getQueryCache(hash string) *OpcodeSet { + s.cacheMu.RLock() + codeSet := s.QueryCache[hash] + s.cacheMu.RUnlock() + return codeSet +} + +func (s *OpcodeSet) setQueryCache(hash string, codeSet *OpcodeSet) { + s.cacheMu.Lock() + s.QueryCache[hash] = codeSet + s.cacheMu.Unlock() +} + +type CompiledCode struct { + Code *Opcode + Linked bool // whether recursive code already have linked + CurLen uintptr + NextLen uintptr +} + +const StartDetectingCyclesAfter = 1000 + +func Load(base uintptr, idx uintptr) uintptr { + addr := base + idx + return **(**uintptr)(unsafe.Pointer(&addr)) +} + +func Store(base uintptr, idx uintptr, p uintptr) { + addr := base + idx + **(**uintptr)(unsafe.Pointer(&addr)) = p +} + +func LoadNPtr(base uintptr, idx uintptr, ptrNum int) uintptr { + addr := base + idx + p := **(**uintptr)(unsafe.Pointer(&addr)) + if p == 0 { + return 0 + } + return PtrToPtr(p) + /* + for i := 0; i < ptrNum; i++ { + if p == 0 { + return p + } + p = PtrToPtr(p) + } + return p + */ +} + +func PtrToUint64(p uintptr) uint64 { return **(**uint64)(unsafe.Pointer(&p)) } +func PtrToFloat32(p uintptr) float32 { return **(**float32)(unsafe.Pointer(&p)) } +func PtrToFloat64(p uintptr) float64 { return **(**float64)(unsafe.Pointer(&p)) } +func PtrToBool(p uintptr) bool { return **(**bool)(unsafe.Pointer(&p)) } +func PtrToBytes(p uintptr) []byte { return **(**[]byte)(unsafe.Pointer(&p)) } +func PtrToNumber(p uintptr) json.Number { return **(**json.Number)(unsafe.Pointer(&p)) } +func PtrToString(p uintptr) string { return **(**string)(unsafe.Pointer(&p)) } +func PtrToSlice(p uintptr) *runtime.SliceHeader { return *(**runtime.SliceHeader)(unsafe.Pointer(&p)) } +func PtrToPtr(p uintptr) uintptr { + return uintptr(**(**unsafe.Pointer)(unsafe.Pointer(&p))) +} +func PtrToNPtr(p uintptr, ptrNum int) uintptr { + for i := 0; i < ptrNum; i++ { + if p == 0 { + return 0 + } + p = PtrToPtr(p) + } + return p +} + +func PtrToUnsafePtr(p uintptr) unsafe.Pointer { + return *(*unsafe.Pointer)(unsafe.Pointer(&p)) +} +func PtrToInterface(code *Opcode, p uintptr) interface{} { + return *(*interface{})(unsafe.Pointer(&emptyInterface{ + typ: code.Type, + ptr: *(*unsafe.Pointer)(unsafe.Pointer(&p)), + })) +} + +func ErrUnsupportedValue(code *Opcode, ptr uintptr) *errors.UnsupportedValueError { + v := *(*interface{})(unsafe.Pointer(&emptyInterface{ + typ: code.Type, + ptr: *(*unsafe.Pointer)(unsafe.Pointer(&ptr)), + })) + return &errors.UnsupportedValueError{ + Value: reflect.ValueOf(v), + Str: fmt.Sprintf("encountered a cycle via %s", code.Type), + } +} + +func ErrUnsupportedFloat(v float64) *errors.UnsupportedValueError { + return &errors.UnsupportedValueError{ + Value: reflect.ValueOf(v), + Str: strconv.FormatFloat(v, 'g', -1, 64), + } +} + +func ErrMarshalerWithCode(code *Opcode, err error) *errors.MarshalerError { + return &errors.MarshalerError{ + Type: runtime.RType2Type(code.Type), + Err: err, + } +} + +type emptyInterface struct { + typ *runtime.Type + ptr unsafe.Pointer +} + +type MapItem struct { + Key []byte + Value []byte +} + +type Mapslice struct { + Items []MapItem +} + +func (m *Mapslice) Len() int { + return len(m.Items) +} + +func (m *Mapslice) Less(i, j int) bool { + return bytes.Compare(m.Items[i].Key, m.Items[j].Key) < 0 +} + +func (m *Mapslice) Swap(i, j int) { + m.Items[i], m.Items[j] = m.Items[j], m.Items[i] +} + +//nolint:structcheck,unused +type mapIter struct { + key unsafe.Pointer + elem unsafe.Pointer + t unsafe.Pointer + h unsafe.Pointer + buckets unsafe.Pointer + bptr unsafe.Pointer + overflow unsafe.Pointer + oldoverflow unsafe.Pointer + startBucket uintptr + offset uint8 + wrapped bool + B uint8 + i uint8 + bucket uintptr + checkBucket uintptr +} + +type MapContext struct { + Start int + First int + Idx int + Slice *Mapslice + Buf []byte + Len int + Iter mapIter +} + +var mapContextPool = sync.Pool{ + New: func() interface{} { + return &MapContext{ + Slice: &Mapslice{}, + } + }, +} + +func NewMapContext(mapLen int, unorderedMap bool) *MapContext { + ctx := mapContextPool.Get().(*MapContext) + if !unorderedMap { + if len(ctx.Slice.Items) < mapLen { + ctx.Slice.Items = make([]MapItem, mapLen) + } else { + ctx.Slice.Items = ctx.Slice.Items[:mapLen] + } + } + ctx.Buf = ctx.Buf[:0] + ctx.Iter = mapIter{} + ctx.Idx = 0 + ctx.Len = mapLen + return ctx +} + +func ReleaseMapContext(c *MapContext) { + mapContextPool.Put(c) +} + +//go:linkname MapIterInit runtime.mapiterinit +//go:noescape +func MapIterInit(mapType *runtime.Type, m unsafe.Pointer, it *mapIter) + +//go:linkname MapIterKey reflect.mapiterkey +//go:noescape +func MapIterKey(it *mapIter) unsafe.Pointer + +//go:linkname MapIterNext reflect.mapiternext +//go:noescape +func MapIterNext(it *mapIter) + +//go:linkname MapLen reflect.maplen +//go:noescape +func MapLen(m unsafe.Pointer) int + +func AppendByteSlice(_ *RuntimeContext, b []byte, src []byte) []byte { + if src == nil { + return append(b, `null`...) + } + encodedLen := base64.StdEncoding.EncodedLen(len(src)) + b = append(b, '"') + pos := len(b) + remainLen := cap(b[pos:]) + var buf []byte + if remainLen > encodedLen { + buf = b[pos : pos+encodedLen] + } else { + buf = make([]byte, encodedLen) + } + base64.StdEncoding.Encode(buf, src) + return append(append(b, buf...), '"') +} + +func AppendFloat32(_ *RuntimeContext, b []byte, v float32) []byte { + f64 := float64(v) + abs := math.Abs(f64) + fmt := byte('f') + // Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right. + if abs != 0 { + f32 := float32(abs) + if f32 < 1e-6 || f32 >= 1e21 { + fmt = 'e' + } + } + return strconv.AppendFloat(b, f64, fmt, -1, 32) +} + +func AppendFloat64(_ *RuntimeContext, b []byte, v float64) []byte { + abs := math.Abs(v) + fmt := byte('f') + // Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right. + if abs != 0 { + if abs < 1e-6 || abs >= 1e21 { + fmt = 'e' + } + } + return strconv.AppendFloat(b, v, fmt, -1, 64) +} + +func AppendBool(_ *RuntimeContext, b []byte, v bool) []byte { + if v { + return append(b, "true"...) + } + return append(b, "false"...) +} + +var ( + floatTable = [256]bool{ + '0': true, + '1': true, + '2': true, + '3': true, + '4': true, + '5': true, + '6': true, + '7': true, + '8': true, + '9': true, + '.': true, + 'e': true, + 'E': true, + '+': true, + '-': true, + } +) + +func AppendNumber(_ *RuntimeContext, b []byte, n json.Number) ([]byte, error) { + if len(n) == 0 { + return append(b, '0'), nil + } + for i := 0; i < len(n); i++ { + if !floatTable[n[i]] { + return nil, fmt.Errorf("json: invalid number literal %q", n) + } + } + b = append(b, n...) + return b, nil +} + +func AppendMarshalJSON(ctx *RuntimeContext, code *Opcode, b []byte, v interface{}) ([]byte, error) { + rv := reflect.ValueOf(v) // convert by dynamic interface type + if (code.Flags & AddrForMarshalerFlags) != 0 { + if rv.CanAddr() { + rv = rv.Addr() + } else { + newV := reflect.New(rv.Type()) + newV.Elem().Set(rv) + rv = newV + } + } + v = rv.Interface() + var bb []byte + if (code.Flags & MarshalerContextFlags) != 0 { + marshaler, ok := v.(marshalerContext) + if !ok { + return AppendNull(ctx, b), nil + } + stdctx := ctx.Option.Context + if ctx.Option.Flag&FieldQueryOption != 0 { + stdctx = SetFieldQueryToContext(stdctx, code.FieldQuery) + } + b, err := marshaler.MarshalJSON(stdctx) + if err != nil { + return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err} + } + bb = b + } else { + marshaler, ok := v.(json.Marshaler) + if !ok { + return AppendNull(ctx, b), nil + } + b, err := marshaler.MarshalJSON() + if err != nil { + return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err} + } + bb = b + } + marshalBuf := ctx.MarshalBuf[:0] + marshalBuf = append(append(marshalBuf, bb...), nul) + compactedBuf, err := compact(b, marshalBuf, (ctx.Option.Flag&HTMLEscapeOption) != 0) + if err != nil { + return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err} + } + ctx.MarshalBuf = marshalBuf + return compactedBuf, nil +} + +func AppendMarshalJSONIndent(ctx *RuntimeContext, code *Opcode, b []byte, v interface{}) ([]byte, error) { + rv := reflect.ValueOf(v) // convert by dynamic interface type + if (code.Flags & AddrForMarshalerFlags) != 0 { + if rv.CanAddr() { + rv = rv.Addr() + } else { + newV := reflect.New(rv.Type()) + newV.Elem().Set(rv) + rv = newV + } + } + v = rv.Interface() + var bb []byte + if (code.Flags & MarshalerContextFlags) != 0 { + marshaler, ok := v.(marshalerContext) + if !ok { + return AppendNull(ctx, b), nil + } + b, err := marshaler.MarshalJSON(ctx.Option.Context) + if err != nil { + return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err} + } + bb = b + } else { + marshaler, ok := v.(json.Marshaler) + if !ok { + return AppendNull(ctx, b), nil + } + b, err := marshaler.MarshalJSON() + if err != nil { + return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err} + } + bb = b + } + marshalBuf := ctx.MarshalBuf[:0] + marshalBuf = append(append(marshalBuf, bb...), nul) + indentedBuf, err := doIndent( + b, + marshalBuf, + string(ctx.Prefix)+strings.Repeat(string(ctx.IndentStr), int(ctx.BaseIndent+code.Indent)), + string(ctx.IndentStr), + (ctx.Option.Flag&HTMLEscapeOption) != 0, + ) + if err != nil { + return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err} + } + ctx.MarshalBuf = marshalBuf + return indentedBuf, nil +} + +func AppendMarshalText(ctx *RuntimeContext, code *Opcode, b []byte, v interface{}) ([]byte, error) { + rv := reflect.ValueOf(v) // convert by dynamic interface type + if (code.Flags & AddrForMarshalerFlags) != 0 { + if rv.CanAddr() { + rv = rv.Addr() + } else { + newV := reflect.New(rv.Type()) + newV.Elem().Set(rv) + rv = newV + } + } + v = rv.Interface() + marshaler, ok := v.(encoding.TextMarshaler) + if !ok { + return AppendNull(ctx, b), nil + } + bytes, err := marshaler.MarshalText() + if err != nil { + return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err} + } + return AppendString(ctx, b, *(*string)(unsafe.Pointer(&bytes))), nil +} + +func AppendMarshalTextIndent(ctx *RuntimeContext, code *Opcode, b []byte, v interface{}) ([]byte, error) { + rv := reflect.ValueOf(v) // convert by dynamic interface type + if (code.Flags & AddrForMarshalerFlags) != 0 { + if rv.CanAddr() { + rv = rv.Addr() + } else { + newV := reflect.New(rv.Type()) + newV.Elem().Set(rv) + rv = newV + } + } + v = rv.Interface() + marshaler, ok := v.(encoding.TextMarshaler) + if !ok { + return AppendNull(ctx, b), nil + } + bytes, err := marshaler.MarshalText() + if err != nil { + return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err} + } + return AppendString(ctx, b, *(*string)(unsafe.Pointer(&bytes))), nil +} + +func AppendNull(_ *RuntimeContext, b []byte) []byte { + return append(b, "null"...) +} + +func AppendComma(_ *RuntimeContext, b []byte) []byte { + return append(b, ',') +} + +func AppendCommaIndent(_ *RuntimeContext, b []byte) []byte { + return append(b, ',', '\n') +} + +func AppendStructEnd(_ *RuntimeContext, b []byte) []byte { + return append(b, '}', ',') +} + +func AppendStructEndIndent(ctx *RuntimeContext, code *Opcode, b []byte) []byte { + b = append(b, '\n') + b = append(b, ctx.Prefix...) + indentNum := ctx.BaseIndent + code.Indent - 1 + for i := uint32(0); i < indentNum; i++ { + b = append(b, ctx.IndentStr...) + } + return append(b, '}', ',', '\n') +} + +func AppendIndent(ctx *RuntimeContext, b []byte, indent uint32) []byte { + b = append(b, ctx.Prefix...) + indentNum := ctx.BaseIndent + indent + for i := uint32(0); i < indentNum; i++ { + b = append(b, ctx.IndentStr...) + } + return b +} + +func IsNilForMarshaler(v interface{}) bool { + rv := reflect.ValueOf(v) + switch rv.Kind() { + case reflect.Bool: + return !rv.Bool() + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return rv.Int() == 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return rv.Uint() == 0 + case reflect.Float32, reflect.Float64: + return math.Float64bits(rv.Float()) == 0 + case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Func: + return rv.IsNil() + case reflect.Slice: + return rv.IsNil() || rv.Len() == 0 + case reflect.String: + return rv.Len() == 0 + } + return false +} diff --git a/vendor/github.com/goccy/go-json/internal/encoder/indent.go b/vendor/github.com/goccy/go-json/internal/encoder/indent.go new file mode 100644 index 000000000..dfe04b5e3 --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/encoder/indent.go @@ -0,0 +1,211 @@ +package encoder + +import ( + "bytes" + "fmt" + + "github.com/goccy/go-json/internal/errors" +) + +func takeIndentSrcRuntimeContext(src []byte) (*RuntimeContext, []byte) { + ctx := TakeRuntimeContext() + buf := ctx.Buf[:0] + buf = append(append(buf, src...), nul) + ctx.Buf = buf + return ctx, buf +} + +func Indent(buf *bytes.Buffer, src []byte, prefix, indentStr string) error { + if len(src) == 0 { + return errors.ErrUnexpectedEndOfJSON("", 0) + } + + srcCtx, srcBuf := takeIndentSrcRuntimeContext(src) + dstCtx := TakeRuntimeContext() + dst := dstCtx.Buf[:0] + + dst, err := indentAndWrite(buf, dst, srcBuf, prefix, indentStr) + if err != nil { + ReleaseRuntimeContext(srcCtx) + ReleaseRuntimeContext(dstCtx) + return err + } + dstCtx.Buf = dst + ReleaseRuntimeContext(srcCtx) + ReleaseRuntimeContext(dstCtx) + return nil +} + +func indentAndWrite(buf *bytes.Buffer, dst []byte, src []byte, prefix, indentStr string) ([]byte, error) { + dst, err := doIndent(dst, src, prefix, indentStr, false) + if err != nil { + return nil, err + } + if _, err := buf.Write(dst); err != nil { + return nil, err + } + return dst, nil +} + +func doIndent(dst, src []byte, prefix, indentStr string, escape bool) ([]byte, error) { + buf, cursor, err := indentValue(dst, src, 0, 0, []byte(prefix), []byte(indentStr), escape) + if err != nil { + return nil, err + } + if err := validateEndBuf(src, cursor); err != nil { + return nil, err + } + return buf, nil +} + +func indentValue( + dst []byte, + src []byte, + indentNum int, + cursor int64, + prefix []byte, + indentBytes []byte, + escape bool) ([]byte, int64, error) { + for { + switch src[cursor] { + case ' ', '\t', '\n', '\r': + cursor++ + continue + case '{': + return indentObject(dst, src, indentNum, cursor, prefix, indentBytes, escape) + case '}': + return nil, 0, errors.ErrSyntax("unexpected character '}'", cursor) + case '[': + return indentArray(dst, src, indentNum, cursor, prefix, indentBytes, escape) + case ']': + return nil, 0, errors.ErrSyntax("unexpected character ']'", cursor) + case '"': + return compactString(dst, src, cursor, escape) + case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + return compactNumber(dst, src, cursor) + case 't': + return compactTrue(dst, src, cursor) + case 'f': + return compactFalse(dst, src, cursor) + case 'n': + return compactNull(dst, src, cursor) + default: + return nil, 0, errors.ErrSyntax(fmt.Sprintf("unexpected character '%c'", src[cursor]), cursor) + } + } +} + +func indentObject( + dst []byte, + src []byte, + indentNum int, + cursor int64, + prefix []byte, + indentBytes []byte, + escape bool) ([]byte, int64, error) { + if src[cursor] == '{' { + dst = append(dst, '{') + } else { + return nil, 0, errors.ErrExpected("expected { character for object value", cursor) + } + cursor = skipWhiteSpace(src, cursor+1) + if src[cursor] == '}' { + dst = append(dst, '}') + return dst, cursor + 1, nil + } + indentNum++ + var err error + for { + dst = append(append(dst, '\n'), prefix...) + for i := 0; i < indentNum; i++ { + dst = append(dst, indentBytes...) + } + cursor = skipWhiteSpace(src, cursor) + dst, cursor, err = compactString(dst, src, cursor, escape) + if err != nil { + return nil, 0, err + } + cursor = skipWhiteSpace(src, cursor) + if src[cursor] != ':' { + return nil, 0, errors.ErrSyntax( + fmt.Sprintf("invalid character '%c' after object key", src[cursor]), + cursor+1, + ) + } + dst = append(dst, ':', ' ') + dst, cursor, err = indentValue(dst, src, indentNum, cursor+1, prefix, indentBytes, escape) + if err != nil { + return nil, 0, err + } + cursor = skipWhiteSpace(src, cursor) + switch src[cursor] { + case '}': + dst = append(append(dst, '\n'), prefix...) + for i := 0; i < indentNum-1; i++ { + dst = append(dst, indentBytes...) + } + dst = append(dst, '}') + cursor++ + return dst, cursor, nil + case ',': + dst = append(dst, ',') + default: + return nil, 0, errors.ErrSyntax( + fmt.Sprintf("invalid character '%c' after object key:value pair", src[cursor]), + cursor+1, + ) + } + cursor++ + } +} + +func indentArray( + dst []byte, + src []byte, + indentNum int, + cursor int64, + prefix []byte, + indentBytes []byte, + escape bool) ([]byte, int64, error) { + if src[cursor] == '[' { + dst = append(dst, '[') + } else { + return nil, 0, errors.ErrExpected("expected [ character for array value", cursor) + } + cursor = skipWhiteSpace(src, cursor+1) + if src[cursor] == ']' { + dst = append(dst, ']') + return dst, cursor + 1, nil + } + indentNum++ + var err error + for { + dst = append(append(dst, '\n'), prefix...) + for i := 0; i < indentNum; i++ { + dst = append(dst, indentBytes...) + } + dst, cursor, err = indentValue(dst, src, indentNum, cursor, prefix, indentBytes, escape) + if err != nil { + return nil, 0, err + } + cursor = skipWhiteSpace(src, cursor) + switch src[cursor] { + case ']': + dst = append(append(dst, '\n'), prefix...) + for i := 0; i < indentNum-1; i++ { + dst = append(dst, indentBytes...) + } + dst = append(dst, ']') + cursor++ + return dst, cursor, nil + case ',': + dst = append(dst, ',') + default: + return nil, 0, errors.ErrSyntax( + fmt.Sprintf("invalid character '%c' after array value", src[cursor]), + cursor+1, + ) + } + cursor++ + } +} diff --git a/vendor/github.com/goccy/go-json/internal/encoder/int.go b/vendor/github.com/goccy/go-json/internal/encoder/int.go new file mode 100644 index 000000000..85f079609 --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/encoder/int.go @@ -0,0 +1,152 @@ +package encoder + +import ( + "unsafe" +) + +var endianness int + +func init() { + var b [2]byte + *(*uint16)(unsafe.Pointer(&b)) = uint16(0xABCD) + + switch b[0] { + case 0xCD: + endianness = 0 // LE + case 0xAB: + endianness = 1 // BE + default: + panic("could not determine endianness") + } +} + +// "00010203...96979899" cast to []uint16 +var intLELookup = [100]uint16{ + 0x3030, 0x3130, 0x3230, 0x3330, 0x3430, 0x3530, 0x3630, 0x3730, 0x3830, 0x3930, + 0x3031, 0x3131, 0x3231, 0x3331, 0x3431, 0x3531, 0x3631, 0x3731, 0x3831, 0x3931, + 0x3032, 0x3132, 0x3232, 0x3332, 0x3432, 0x3532, 0x3632, 0x3732, 0x3832, 0x3932, + 0x3033, 0x3133, 0x3233, 0x3333, 0x3433, 0x3533, 0x3633, 0x3733, 0x3833, 0x3933, + 0x3034, 0x3134, 0x3234, 0x3334, 0x3434, 0x3534, 0x3634, 0x3734, 0x3834, 0x3934, + 0x3035, 0x3135, 0x3235, 0x3335, 0x3435, 0x3535, 0x3635, 0x3735, 0x3835, 0x3935, + 0x3036, 0x3136, 0x3236, 0x3336, 0x3436, 0x3536, 0x3636, 0x3736, 0x3836, 0x3936, + 0x3037, 0x3137, 0x3237, 0x3337, 0x3437, 0x3537, 0x3637, 0x3737, 0x3837, 0x3937, + 0x3038, 0x3138, 0x3238, 0x3338, 0x3438, 0x3538, 0x3638, 0x3738, 0x3838, 0x3938, + 0x3039, 0x3139, 0x3239, 0x3339, 0x3439, 0x3539, 0x3639, 0x3739, 0x3839, 0x3939, +} + +var intBELookup = [100]uint16{ + 0x3030, 0x3031, 0x3032, 0x3033, 0x3034, 0x3035, 0x3036, 0x3037, 0x3038, 0x3039, + 0x3130, 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3136, 0x3137, 0x3138, 0x3139, + 0x3230, 0x3231, 0x3232, 0x3233, 0x3234, 0x3235, 0x3236, 0x3237, 0x3238, 0x3239, + 0x3330, 0x3331, 0x3332, 0x3333, 0x3334, 0x3335, 0x3336, 0x3337, 0x3338, 0x3339, + 0x3430, 0x3431, 0x3432, 0x3433, 0x3434, 0x3435, 0x3436, 0x3437, 0x3438, 0x3439, + 0x3530, 0x3531, 0x3532, 0x3533, 0x3534, 0x3535, 0x3536, 0x3537, 0x3538, 0x3539, + 0x3630, 0x3631, 0x3632, 0x3633, 0x3634, 0x3635, 0x3636, 0x3637, 0x3638, 0x3639, + 0x3730, 0x3731, 0x3732, 0x3733, 0x3734, 0x3735, 0x3736, 0x3737, 0x3738, 0x3739, + 0x3830, 0x3831, 0x3832, 0x3833, 0x3834, 0x3835, 0x3836, 0x3837, 0x3838, 0x3839, + 0x3930, 0x3931, 0x3932, 0x3933, 0x3934, 0x3935, 0x3936, 0x3937, 0x3938, 0x3939, +} + +var intLookup = [2]*[100]uint16{&intLELookup, &intBELookup} + +func numMask(numBitSize uint8) uint64 { + return 1<>(code.NumBitSize-1))&1 == 1 + if !negative { + if n < 10 { + return append(out, byte(n+'0')) + } else if n < 100 { + u := intLELookup[n] + return append(out, byte(u), byte(u>>8)) + } + } else { + n = -n & mask + } + + lookup := intLookup[endianness] + + var b [22]byte + u := (*[11]uint16)(unsafe.Pointer(&b)) + i := 11 + + for n >= 100 { + j := n % 100 + n /= 100 + i-- + u[i] = lookup[j] + } + + i-- + u[i] = lookup[n] + + i *= 2 // convert to byte index + if n < 10 { + i++ // remove leading zero + } + if negative { + i-- + b[i] = '-' + } + + return append(out, b[i:]...) +} + +func AppendUint(_ *RuntimeContext, out []byte, p uintptr, code *Opcode) []byte { + var u64 uint64 + switch code.NumBitSize { + case 8: + u64 = (uint64)(**(**uint8)(unsafe.Pointer(&p))) + case 16: + u64 = (uint64)(**(**uint16)(unsafe.Pointer(&p))) + case 32: + u64 = (uint64)(**(**uint32)(unsafe.Pointer(&p))) + case 64: + u64 = **(**uint64)(unsafe.Pointer(&p)) + } + mask := numMask(code.NumBitSize) + n := u64 & mask + if n < 10 { + return append(out, byte(n+'0')) + } else if n < 100 { + u := intLELookup[n] + return append(out, byte(u), byte(u>>8)) + } + + lookup := intLookup[endianness] + + var b [22]byte + u := (*[11]uint16)(unsafe.Pointer(&b)) + i := 11 + + for n >= 100 { + j := n % 100 + n /= 100 + i-- + u[i] = lookup[j] + } + + i-- + u[i] = lookup[n] + + i *= 2 // convert to byte index + if n < 10 { + i++ // remove leading zero + } + return append(out, b[i:]...) +} diff --git a/vendor/github.com/goccy/go-json/internal/encoder/map112.go b/vendor/github.com/goccy/go-json/internal/encoder/map112.go new file mode 100644 index 000000000..e96ffadf7 --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/encoder/map112.go @@ -0,0 +1,9 @@ +//go:build !go1.13 +// +build !go1.13 + +package encoder + +import "unsafe" + +//go:linkname MapIterValue reflect.mapitervalue +func MapIterValue(it *mapIter) unsafe.Pointer diff --git a/vendor/github.com/goccy/go-json/internal/encoder/map113.go b/vendor/github.com/goccy/go-json/internal/encoder/map113.go new file mode 100644 index 000000000..9b69dcc36 --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/encoder/map113.go @@ -0,0 +1,9 @@ +//go:build go1.13 +// +build go1.13 + +package encoder + +import "unsafe" + +//go:linkname MapIterValue reflect.mapiterelem +func MapIterValue(it *mapIter) unsafe.Pointer diff --git a/vendor/github.com/goccy/go-json/internal/encoder/opcode.go b/vendor/github.com/goccy/go-json/internal/encoder/opcode.go new file mode 100644 index 000000000..df22f5542 --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/encoder/opcode.go @@ -0,0 +1,752 @@ +package encoder + +import ( + "bytes" + "fmt" + "sort" + "strings" + "unsafe" + + "github.com/goccy/go-json/internal/runtime" +) + +const uintptrSize = 4 << (^uintptr(0) >> 63) + +type OpFlags uint16 + +const ( + AnonymousHeadFlags OpFlags = 1 << 0 + AnonymousKeyFlags OpFlags = 1 << 1 + IndirectFlags OpFlags = 1 << 2 + IsTaggedKeyFlags OpFlags = 1 << 3 + NilCheckFlags OpFlags = 1 << 4 + AddrForMarshalerFlags OpFlags = 1 << 5 + IsNextOpPtrTypeFlags OpFlags = 1 << 6 + IsNilableTypeFlags OpFlags = 1 << 7 + MarshalerContextFlags OpFlags = 1 << 8 + NonEmptyInterfaceFlags OpFlags = 1 << 9 +) + +type Opcode struct { + Op OpType // operation type + Idx uint32 // offset to access ptr + Next *Opcode // next opcode + End *Opcode // array/slice/struct/map end + NextField *Opcode // next struct field + Key string // struct field key + Offset uint32 // offset size from struct header + PtrNum uint8 // pointer number: e.g. double pointer is 2. + NumBitSize uint8 + Flags OpFlags + + Type *runtime.Type // go type + Jmp *CompiledCode // for recursive call + FieldQuery *FieldQuery // field query for Interface / MarshalJSON / MarshalText + ElemIdx uint32 // offset to access array/slice elem + Length uint32 // offset to access slice length or array length + Indent uint32 // indent number + Size uint32 // array/slice elem size + DisplayIdx uint32 // opcode index + DisplayKey string // key text to display +} + +func (c *Opcode) Validate() error { + var prevIdx uint32 + for code := c; !code.IsEnd(); { + if prevIdx != 0 { + if code.DisplayIdx != prevIdx+1 { + return fmt.Errorf( + "invalid index. previous display index is %d but next is %d. dump = %s", + prevIdx, code.DisplayIdx, c.Dump(), + ) + } + } + prevIdx = code.DisplayIdx + code = code.IterNext() + } + return nil +} + +func (c *Opcode) IterNext() *Opcode { + if c == nil { + return nil + } + switch c.Op.CodeType() { + case CodeArrayElem, CodeSliceElem, CodeMapKey: + return c.End + default: + return c.Next + } +} + +func (c *Opcode) IsEnd() bool { + if c == nil { + return true + } + return c.Op == OpEnd || c.Op == OpInterfaceEnd || c.Op == OpRecursiveEnd +} + +func (c *Opcode) MaxIdx() uint32 { + max := uint32(0) + for _, value := range []uint32{ + c.Idx, + c.ElemIdx, + c.Length, + c.Size, + } { + if max < value { + max = value + } + } + return max +} + +func (c *Opcode) ToHeaderType(isString bool) OpType { + switch c.Op { + case OpInt: + if isString { + return OpStructHeadIntString + } + return OpStructHeadInt + case OpIntPtr: + if isString { + return OpStructHeadIntPtrString + } + return OpStructHeadIntPtr + case OpUint: + if isString { + return OpStructHeadUintString + } + return OpStructHeadUint + case OpUintPtr: + if isString { + return OpStructHeadUintPtrString + } + return OpStructHeadUintPtr + case OpFloat32: + if isString { + return OpStructHeadFloat32String + } + return OpStructHeadFloat32 + case OpFloat32Ptr: + if isString { + return OpStructHeadFloat32PtrString + } + return OpStructHeadFloat32Ptr + case OpFloat64: + if isString { + return OpStructHeadFloat64String + } + return OpStructHeadFloat64 + case OpFloat64Ptr: + if isString { + return OpStructHeadFloat64PtrString + } + return OpStructHeadFloat64Ptr + case OpString: + if isString { + return OpStructHeadStringString + } + return OpStructHeadString + case OpStringPtr: + if isString { + return OpStructHeadStringPtrString + } + return OpStructHeadStringPtr + case OpNumber: + if isString { + return OpStructHeadNumberString + } + return OpStructHeadNumber + case OpNumberPtr: + if isString { + return OpStructHeadNumberPtrString + } + return OpStructHeadNumberPtr + case OpBool: + if isString { + return OpStructHeadBoolString + } + return OpStructHeadBool + case OpBoolPtr: + if isString { + return OpStructHeadBoolPtrString + } + return OpStructHeadBoolPtr + case OpBytes: + return OpStructHeadBytes + case OpBytesPtr: + return OpStructHeadBytesPtr + case OpMap: + return OpStructHeadMap + case OpMapPtr: + c.Op = OpMap + return OpStructHeadMapPtr + case OpArray: + return OpStructHeadArray + case OpArrayPtr: + c.Op = OpArray + return OpStructHeadArrayPtr + case OpSlice: + return OpStructHeadSlice + case OpSlicePtr: + c.Op = OpSlice + return OpStructHeadSlicePtr + case OpMarshalJSON: + return OpStructHeadMarshalJSON + case OpMarshalJSONPtr: + return OpStructHeadMarshalJSONPtr + case OpMarshalText: + return OpStructHeadMarshalText + case OpMarshalTextPtr: + return OpStructHeadMarshalTextPtr + } + return OpStructHead +} + +func (c *Opcode) ToFieldType(isString bool) OpType { + switch c.Op { + case OpInt: + if isString { + return OpStructFieldIntString + } + return OpStructFieldInt + case OpIntPtr: + if isString { + return OpStructFieldIntPtrString + } + return OpStructFieldIntPtr + case OpUint: + if isString { + return OpStructFieldUintString + } + return OpStructFieldUint + case OpUintPtr: + if isString { + return OpStructFieldUintPtrString + } + return OpStructFieldUintPtr + case OpFloat32: + if isString { + return OpStructFieldFloat32String + } + return OpStructFieldFloat32 + case OpFloat32Ptr: + if isString { + return OpStructFieldFloat32PtrString + } + return OpStructFieldFloat32Ptr + case OpFloat64: + if isString { + return OpStructFieldFloat64String + } + return OpStructFieldFloat64 + case OpFloat64Ptr: + if isString { + return OpStructFieldFloat64PtrString + } + return OpStructFieldFloat64Ptr + case OpString: + if isString { + return OpStructFieldStringString + } + return OpStructFieldString + case OpStringPtr: + if isString { + return OpStructFieldStringPtrString + } + return OpStructFieldStringPtr + case OpNumber: + if isString { + return OpStructFieldNumberString + } + return OpStructFieldNumber + case OpNumberPtr: + if isString { + return OpStructFieldNumberPtrString + } + return OpStructFieldNumberPtr + case OpBool: + if isString { + return OpStructFieldBoolString + } + return OpStructFieldBool + case OpBoolPtr: + if isString { + return OpStructFieldBoolPtrString + } + return OpStructFieldBoolPtr + case OpBytes: + return OpStructFieldBytes + case OpBytesPtr: + return OpStructFieldBytesPtr + case OpMap: + return OpStructFieldMap + case OpMapPtr: + c.Op = OpMap + return OpStructFieldMapPtr + case OpArray: + return OpStructFieldArray + case OpArrayPtr: + c.Op = OpArray + return OpStructFieldArrayPtr + case OpSlice: + return OpStructFieldSlice + case OpSlicePtr: + c.Op = OpSlice + return OpStructFieldSlicePtr + case OpMarshalJSON: + return OpStructFieldMarshalJSON + case OpMarshalJSONPtr: + return OpStructFieldMarshalJSONPtr + case OpMarshalText: + return OpStructFieldMarshalText + case OpMarshalTextPtr: + return OpStructFieldMarshalTextPtr + } + return OpStructField +} + +func newOpCode(ctx *compileContext, typ *runtime.Type, op OpType) *Opcode { + return newOpCodeWithNext(ctx, typ, op, newEndOp(ctx, typ)) +} + +func opcodeOffset(idx int) uint32 { + return uint32(idx) * uintptrSize +} + +func getCodeAddrByIdx(head *Opcode, idx uint32) *Opcode { + addr := uintptr(unsafe.Pointer(head)) + uintptr(idx)*unsafe.Sizeof(Opcode{}) + return *(**Opcode)(unsafe.Pointer(&addr)) +} + +func copyOpcode(code *Opcode) *Opcode { + codeNum := ToEndCode(code).DisplayIdx + 1 + codeSlice := make([]Opcode, codeNum) + head := (*Opcode)((*runtime.SliceHeader)(unsafe.Pointer(&codeSlice)).Data) + ptr := head + c := code + for { + *ptr = Opcode{ + Op: c.Op, + Key: c.Key, + PtrNum: c.PtrNum, + NumBitSize: c.NumBitSize, + Flags: c.Flags, + Idx: c.Idx, + Offset: c.Offset, + Type: c.Type, + FieldQuery: c.FieldQuery, + DisplayIdx: c.DisplayIdx, + DisplayKey: c.DisplayKey, + ElemIdx: c.ElemIdx, + Length: c.Length, + Size: c.Size, + Indent: c.Indent, + Jmp: c.Jmp, + } + if c.End != nil { + ptr.End = getCodeAddrByIdx(head, c.End.DisplayIdx) + } + if c.NextField != nil { + ptr.NextField = getCodeAddrByIdx(head, c.NextField.DisplayIdx) + } + if c.Next != nil { + ptr.Next = getCodeAddrByIdx(head, c.Next.DisplayIdx) + } + if c.IsEnd() { + break + } + ptr = getCodeAddrByIdx(head, c.DisplayIdx+1) + c = c.IterNext() + } + return head +} + +func setTotalLengthToInterfaceOp(code *Opcode) { + for c := code; !c.IsEnd(); { + if c.Op == OpInterface || c.Op == OpInterfacePtr { + c.Length = uint32(code.TotalLength()) + } + c = c.IterNext() + } +} + +func ToEndCode(code *Opcode) *Opcode { + c := code + for !c.IsEnd() { + c = c.IterNext() + } + return c +} + +func copyToInterfaceOpcode(code *Opcode) *Opcode { + copied := copyOpcode(code) + c := copied + c = ToEndCode(c) + c.Idx += uintptrSize + c.ElemIdx = c.Idx + uintptrSize + c.Length = c.Idx + 2*uintptrSize + c.Op = OpInterfaceEnd + return copied +} + +func newOpCodeWithNext(ctx *compileContext, typ *runtime.Type, op OpType, next *Opcode) *Opcode { + return &Opcode{ + Op: op, + Idx: opcodeOffset(ctx.ptrIndex), + Next: next, + Type: typ, + DisplayIdx: ctx.opcodeIndex, + Indent: ctx.indent, + } +} + +func newEndOp(ctx *compileContext, typ *runtime.Type) *Opcode { + return newOpCodeWithNext(ctx, typ, OpEnd, nil) +} + +func (c *Opcode) TotalLength() int { + var idx int + code := c + for !code.IsEnd() { + maxIdx := int(code.MaxIdx() / uintptrSize) + if idx < maxIdx { + idx = maxIdx + } + if code.Op == OpRecursiveEnd { + break + } + code = code.IterNext() + } + maxIdx := int(code.MaxIdx() / uintptrSize) + if idx < maxIdx { + idx = maxIdx + } + return idx + 1 +} + +func (c *Opcode) dumpHead(code *Opcode) string { + var length uint32 + if code.Op.CodeType() == CodeArrayHead { + length = code.Length + } else { + length = code.Length / uintptrSize + } + return fmt.Sprintf( + `[%03d]%s%s ([idx:%d][elemIdx:%d][length:%d])`, + code.DisplayIdx, + strings.Repeat("-", int(code.Indent)), + code.Op, + code.Idx/uintptrSize, + code.ElemIdx/uintptrSize, + length, + ) +} + +func (c *Opcode) dumpMapHead(code *Opcode) string { + return fmt.Sprintf( + `[%03d]%s%s ([idx:%d])`, + code.DisplayIdx, + strings.Repeat("-", int(code.Indent)), + code.Op, + code.Idx/uintptrSize, + ) +} + +func (c *Opcode) dumpMapEnd(code *Opcode) string { + return fmt.Sprintf( + `[%03d]%s%s ([idx:%d])`, + code.DisplayIdx, + strings.Repeat("-", int(code.Indent)), + code.Op, + code.Idx/uintptrSize, + ) +} + +func (c *Opcode) dumpElem(code *Opcode) string { + var length uint32 + if code.Op.CodeType() == CodeArrayElem { + length = code.Length + } else { + length = code.Length / uintptrSize + } + return fmt.Sprintf( + `[%03d]%s%s ([idx:%d][elemIdx:%d][length:%d][size:%d])`, + code.DisplayIdx, + strings.Repeat("-", int(code.Indent)), + code.Op, + code.Idx/uintptrSize, + code.ElemIdx/uintptrSize, + length, + code.Size, + ) +} + +func (c *Opcode) dumpField(code *Opcode) string { + return fmt.Sprintf( + `[%03d]%s%s ([idx:%d][key:%s][offset:%d])`, + code.DisplayIdx, + strings.Repeat("-", int(code.Indent)), + code.Op, + code.Idx/uintptrSize, + code.DisplayKey, + code.Offset, + ) +} + +func (c *Opcode) dumpKey(code *Opcode) string { + return fmt.Sprintf( + `[%03d]%s%s ([idx:%d])`, + code.DisplayIdx, + strings.Repeat("-", int(code.Indent)), + code.Op, + code.Idx/uintptrSize, + ) +} + +func (c *Opcode) dumpValue(code *Opcode) string { + return fmt.Sprintf( + `[%03d]%s%s ([idx:%d])`, + code.DisplayIdx, + strings.Repeat("-", int(code.Indent)), + code.Op, + code.Idx/uintptrSize, + ) +} + +func (c *Opcode) Dump() string { + codes := []string{} + for code := c; !code.IsEnd(); { + switch code.Op.CodeType() { + case CodeSliceHead: + codes = append(codes, c.dumpHead(code)) + code = code.Next + case CodeMapHead: + codes = append(codes, c.dumpMapHead(code)) + code = code.Next + case CodeArrayElem, CodeSliceElem: + codes = append(codes, c.dumpElem(code)) + code = code.End + case CodeMapKey: + codes = append(codes, c.dumpKey(code)) + code = code.End + case CodeMapValue: + codes = append(codes, c.dumpValue(code)) + code = code.Next + case CodeMapEnd: + codes = append(codes, c.dumpMapEnd(code)) + code = code.Next + case CodeStructField: + codes = append(codes, c.dumpField(code)) + code = code.Next + case CodeStructEnd: + codes = append(codes, c.dumpField(code)) + code = code.Next + default: + codes = append(codes, fmt.Sprintf( + "[%03d]%s%s ([idx:%d])", + code.DisplayIdx, + strings.Repeat("-", int(code.Indent)), + code.Op, + code.Idx/uintptrSize, + )) + code = code.Next + } + } + return strings.Join(codes, "\n") +} + +func (c *Opcode) DumpDOT() string { + type edge struct { + from, to *Opcode + label string + weight int + } + var edges []edge + + b := &bytes.Buffer{} + fmt.Fprintf(b, "digraph \"%p\" {\n", c.Type) + fmt.Fprintln(b, "mclimit=1.5;\nrankdir=TD;\nordering=out;\nnode[shape=box];") + for code := c; !code.IsEnd(); { + label := code.Op.String() + fmt.Fprintf(b, "\"%p\" [label=%q];\n", code, label) + if p := code.Next; p != nil { + edges = append(edges, edge{ + from: code, + to: p, + label: "Next", + weight: 10, + }) + } + if p := code.NextField; p != nil { + edges = append(edges, edge{ + from: code, + to: p, + label: "NextField", + weight: 2, + }) + } + if p := code.End; p != nil { + edges = append(edges, edge{ + from: code, + to: p, + label: "End", + weight: 1, + }) + } + if p := code.Jmp; p != nil { + edges = append(edges, edge{ + from: code, + to: p.Code, + label: "Jmp", + weight: 1, + }) + } + + switch code.Op.CodeType() { + case CodeSliceHead: + code = code.Next + case CodeMapHead: + code = code.Next + case CodeArrayElem, CodeSliceElem: + code = code.End + case CodeMapKey: + code = code.End + case CodeMapValue: + code = code.Next + case CodeMapEnd: + code = code.Next + case CodeStructField: + code = code.Next + case CodeStructEnd: + code = code.Next + default: + code = code.Next + } + if code.IsEnd() { + fmt.Fprintf(b, "\"%p\" [label=%q];\n", code, code.Op.String()) + } + } + sort.Slice(edges, func(i, j int) bool { + return edges[i].to.DisplayIdx < edges[j].to.DisplayIdx + }) + for _, e := range edges { + fmt.Fprintf(b, "\"%p\" -> \"%p\" [label=%q][weight=%d];\n", e.from, e.to, e.label, e.weight) + } + fmt.Fprint(b, "}") + return b.String() +} + +func newSliceHeaderCode(ctx *compileContext, typ *runtime.Type) *Opcode { + idx := opcodeOffset(ctx.ptrIndex) + ctx.incPtrIndex() + elemIdx := opcodeOffset(ctx.ptrIndex) + ctx.incPtrIndex() + length := opcodeOffset(ctx.ptrIndex) + return &Opcode{ + Op: OpSlice, + Type: typ, + Idx: idx, + DisplayIdx: ctx.opcodeIndex, + ElemIdx: elemIdx, + Length: length, + Indent: ctx.indent, + } +} + +func newSliceElemCode(ctx *compileContext, typ *runtime.Type, head *Opcode, size uintptr) *Opcode { + return &Opcode{ + Op: OpSliceElem, + Type: typ, + Idx: head.Idx, + DisplayIdx: ctx.opcodeIndex, + ElemIdx: head.ElemIdx, + Length: head.Length, + Indent: ctx.indent, + Size: uint32(size), + } +} + +func newArrayHeaderCode(ctx *compileContext, typ *runtime.Type, alen int) *Opcode { + idx := opcodeOffset(ctx.ptrIndex) + ctx.incPtrIndex() + elemIdx := opcodeOffset(ctx.ptrIndex) + return &Opcode{ + Op: OpArray, + Type: typ, + Idx: idx, + DisplayIdx: ctx.opcodeIndex, + ElemIdx: elemIdx, + Indent: ctx.indent, + Length: uint32(alen), + } +} + +func newArrayElemCode(ctx *compileContext, typ *runtime.Type, head *Opcode, length int, size uintptr) *Opcode { + return &Opcode{ + Op: OpArrayElem, + Type: typ, + Idx: head.Idx, + DisplayIdx: ctx.opcodeIndex, + ElemIdx: head.ElemIdx, + Length: uint32(length), + Indent: ctx.indent, + Size: uint32(size), + } +} + +func newMapHeaderCode(ctx *compileContext, typ *runtime.Type) *Opcode { + idx := opcodeOffset(ctx.ptrIndex) + ctx.incPtrIndex() + return &Opcode{ + Op: OpMap, + Type: typ, + Idx: idx, + DisplayIdx: ctx.opcodeIndex, + Indent: ctx.indent, + } +} + +func newMapKeyCode(ctx *compileContext, typ *runtime.Type, head *Opcode) *Opcode { + return &Opcode{ + Op: OpMapKey, + Type: typ, + Idx: head.Idx, + DisplayIdx: ctx.opcodeIndex, + Indent: ctx.indent, + } +} + +func newMapValueCode(ctx *compileContext, typ *runtime.Type, head *Opcode) *Opcode { + return &Opcode{ + Op: OpMapValue, + Type: typ, + Idx: head.Idx, + DisplayIdx: ctx.opcodeIndex, + Indent: ctx.indent, + } +} + +func newMapEndCode(ctx *compileContext, typ *runtime.Type, head *Opcode) *Opcode { + return &Opcode{ + Op: OpMapEnd, + Type: typ, + Idx: head.Idx, + DisplayIdx: ctx.opcodeIndex, + Indent: ctx.indent, + Next: newEndOp(ctx, typ), + } +} + +func newRecursiveCode(ctx *compileContext, typ *runtime.Type, jmp *CompiledCode) *Opcode { + return &Opcode{ + Op: OpRecursive, + Type: typ, + Idx: opcodeOffset(ctx.ptrIndex), + Next: newEndOp(ctx, typ), + DisplayIdx: ctx.opcodeIndex, + Indent: ctx.indent, + Jmp: jmp, + } +} diff --git a/vendor/github.com/goccy/go-json/internal/encoder/option.go b/vendor/github.com/goccy/go-json/internal/encoder/option.go new file mode 100644 index 000000000..12c58e46c --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/encoder/option.go @@ -0,0 +1,48 @@ +package encoder + +import ( + "context" + "io" +) + +type OptionFlag uint8 + +const ( + HTMLEscapeOption OptionFlag = 1 << iota + IndentOption + UnorderedMapOption + DebugOption + ColorizeOption + ContextOption + NormalizeUTF8Option + FieldQueryOption +) + +type Option struct { + Flag OptionFlag + ColorScheme *ColorScheme + Context context.Context + DebugOut io.Writer + DebugDOTOut io.WriteCloser +} + +type EncodeFormat struct { + Header string + Footer string +} + +type EncodeFormatScheme struct { + Int EncodeFormat + Uint EncodeFormat + Float EncodeFormat + Bool EncodeFormat + String EncodeFormat + Binary EncodeFormat + ObjectKey EncodeFormat + Null EncodeFormat +} + +type ( + ColorScheme = EncodeFormatScheme + ColorFormat = EncodeFormat +) diff --git a/vendor/github.com/goccy/go-json/internal/encoder/optype.go b/vendor/github.com/goccy/go-json/internal/encoder/optype.go new file mode 100644 index 000000000..5c1241b47 --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/encoder/optype.go @@ -0,0 +1,932 @@ +// Code generated by internal/cmd/generator. DO NOT EDIT! +package encoder + +import ( + "strings" +) + +type CodeType int + +const ( + CodeOp CodeType = 0 + CodeArrayHead CodeType = 1 + CodeArrayElem CodeType = 2 + CodeSliceHead CodeType = 3 + CodeSliceElem CodeType = 4 + CodeMapHead CodeType = 5 + CodeMapKey CodeType = 6 + CodeMapValue CodeType = 7 + CodeMapEnd CodeType = 8 + CodeRecursive CodeType = 9 + CodeStructField CodeType = 10 + CodeStructEnd CodeType = 11 +) + +var opTypeStrings = [400]string{ + "End", + "Interface", + "Ptr", + "SliceElem", + "SliceEnd", + "ArrayElem", + "ArrayEnd", + "MapKey", + "MapValue", + "MapEnd", + "Recursive", + "RecursivePtr", + "RecursiveEnd", + "InterfaceEnd", + "Int", + "Uint", + "Float32", + "Float64", + "Bool", + "String", + "Bytes", + "Number", + "Array", + "Map", + "Slice", + "Struct", + "MarshalJSON", + "MarshalText", + "IntString", + "UintString", + "Float32String", + "Float64String", + "BoolString", + "StringString", + "NumberString", + "IntPtr", + "UintPtr", + "Float32Ptr", + "Float64Ptr", + "BoolPtr", + "StringPtr", + "BytesPtr", + "NumberPtr", + "ArrayPtr", + "MapPtr", + "SlicePtr", + "MarshalJSONPtr", + "MarshalTextPtr", + "InterfacePtr", + "IntPtrString", + "UintPtrString", + "Float32PtrString", + "Float64PtrString", + "BoolPtrString", + "StringPtrString", + "NumberPtrString", + "StructHeadInt", + "StructHeadOmitEmptyInt", + "StructPtrHeadInt", + "StructPtrHeadOmitEmptyInt", + "StructHeadUint", + "StructHeadOmitEmptyUint", + "StructPtrHeadUint", + "StructPtrHeadOmitEmptyUint", + "StructHeadFloat32", + "StructHeadOmitEmptyFloat32", + "StructPtrHeadFloat32", + "StructPtrHeadOmitEmptyFloat32", + "StructHeadFloat64", + "StructHeadOmitEmptyFloat64", + "StructPtrHeadFloat64", + "StructPtrHeadOmitEmptyFloat64", + "StructHeadBool", + "StructHeadOmitEmptyBool", + "StructPtrHeadBool", + "StructPtrHeadOmitEmptyBool", + "StructHeadString", + "StructHeadOmitEmptyString", + "StructPtrHeadString", + "StructPtrHeadOmitEmptyString", + "StructHeadBytes", + "StructHeadOmitEmptyBytes", + "StructPtrHeadBytes", + "StructPtrHeadOmitEmptyBytes", + "StructHeadNumber", + "StructHeadOmitEmptyNumber", + "StructPtrHeadNumber", + "StructPtrHeadOmitEmptyNumber", + "StructHeadArray", + "StructHeadOmitEmptyArray", + "StructPtrHeadArray", + "StructPtrHeadOmitEmptyArray", + "StructHeadMap", + "StructHeadOmitEmptyMap", + "StructPtrHeadMap", + "StructPtrHeadOmitEmptyMap", + "StructHeadSlice", + "StructHeadOmitEmptySlice", + "StructPtrHeadSlice", + "StructPtrHeadOmitEmptySlice", + "StructHeadStruct", + "StructHeadOmitEmptyStruct", + "StructPtrHeadStruct", + "StructPtrHeadOmitEmptyStruct", + "StructHeadMarshalJSON", + "StructHeadOmitEmptyMarshalJSON", + "StructPtrHeadMarshalJSON", + "StructPtrHeadOmitEmptyMarshalJSON", + "StructHeadMarshalText", + "StructHeadOmitEmptyMarshalText", + "StructPtrHeadMarshalText", + "StructPtrHeadOmitEmptyMarshalText", + "StructHeadIntString", + "StructHeadOmitEmptyIntString", + "StructPtrHeadIntString", + "StructPtrHeadOmitEmptyIntString", + "StructHeadUintString", + "StructHeadOmitEmptyUintString", + "StructPtrHeadUintString", + "StructPtrHeadOmitEmptyUintString", + "StructHeadFloat32String", + "StructHeadOmitEmptyFloat32String", + "StructPtrHeadFloat32String", + "StructPtrHeadOmitEmptyFloat32String", + "StructHeadFloat64String", + "StructHeadOmitEmptyFloat64String", + "StructPtrHeadFloat64String", + "StructPtrHeadOmitEmptyFloat64String", + "StructHeadBoolString", + "StructHeadOmitEmptyBoolString", + "StructPtrHeadBoolString", + "StructPtrHeadOmitEmptyBoolString", + "StructHeadStringString", + "StructHeadOmitEmptyStringString", + "StructPtrHeadStringString", + "StructPtrHeadOmitEmptyStringString", + "StructHeadNumberString", + "StructHeadOmitEmptyNumberString", + "StructPtrHeadNumberString", + "StructPtrHeadOmitEmptyNumberString", + "StructHeadIntPtr", + "StructHeadOmitEmptyIntPtr", + "StructPtrHeadIntPtr", + "StructPtrHeadOmitEmptyIntPtr", + "StructHeadUintPtr", + "StructHeadOmitEmptyUintPtr", + "StructPtrHeadUintPtr", + "StructPtrHeadOmitEmptyUintPtr", + "StructHeadFloat32Ptr", + "StructHeadOmitEmptyFloat32Ptr", + "StructPtrHeadFloat32Ptr", + "StructPtrHeadOmitEmptyFloat32Ptr", + "StructHeadFloat64Ptr", + "StructHeadOmitEmptyFloat64Ptr", + "StructPtrHeadFloat64Ptr", + "StructPtrHeadOmitEmptyFloat64Ptr", + "StructHeadBoolPtr", + "StructHeadOmitEmptyBoolPtr", + "StructPtrHeadBoolPtr", + "StructPtrHeadOmitEmptyBoolPtr", + "StructHeadStringPtr", + "StructHeadOmitEmptyStringPtr", + "StructPtrHeadStringPtr", + "StructPtrHeadOmitEmptyStringPtr", + "StructHeadBytesPtr", + "StructHeadOmitEmptyBytesPtr", + "StructPtrHeadBytesPtr", + "StructPtrHeadOmitEmptyBytesPtr", + "StructHeadNumberPtr", + "StructHeadOmitEmptyNumberPtr", + "StructPtrHeadNumberPtr", + "StructPtrHeadOmitEmptyNumberPtr", + "StructHeadArrayPtr", + "StructHeadOmitEmptyArrayPtr", + "StructPtrHeadArrayPtr", + "StructPtrHeadOmitEmptyArrayPtr", + "StructHeadMapPtr", + "StructHeadOmitEmptyMapPtr", + "StructPtrHeadMapPtr", + "StructPtrHeadOmitEmptyMapPtr", + "StructHeadSlicePtr", + "StructHeadOmitEmptySlicePtr", + "StructPtrHeadSlicePtr", + "StructPtrHeadOmitEmptySlicePtr", + "StructHeadMarshalJSONPtr", + "StructHeadOmitEmptyMarshalJSONPtr", + "StructPtrHeadMarshalJSONPtr", + "StructPtrHeadOmitEmptyMarshalJSONPtr", + "StructHeadMarshalTextPtr", + "StructHeadOmitEmptyMarshalTextPtr", + "StructPtrHeadMarshalTextPtr", + "StructPtrHeadOmitEmptyMarshalTextPtr", + "StructHeadInterfacePtr", + "StructHeadOmitEmptyInterfacePtr", + "StructPtrHeadInterfacePtr", + "StructPtrHeadOmitEmptyInterfacePtr", + "StructHeadIntPtrString", + "StructHeadOmitEmptyIntPtrString", + "StructPtrHeadIntPtrString", + "StructPtrHeadOmitEmptyIntPtrString", + "StructHeadUintPtrString", + "StructHeadOmitEmptyUintPtrString", + "StructPtrHeadUintPtrString", + "StructPtrHeadOmitEmptyUintPtrString", + "StructHeadFloat32PtrString", + "StructHeadOmitEmptyFloat32PtrString", + "StructPtrHeadFloat32PtrString", + "StructPtrHeadOmitEmptyFloat32PtrString", + "StructHeadFloat64PtrString", + "StructHeadOmitEmptyFloat64PtrString", + "StructPtrHeadFloat64PtrString", + "StructPtrHeadOmitEmptyFloat64PtrString", + "StructHeadBoolPtrString", + "StructHeadOmitEmptyBoolPtrString", + "StructPtrHeadBoolPtrString", + "StructPtrHeadOmitEmptyBoolPtrString", + "StructHeadStringPtrString", + "StructHeadOmitEmptyStringPtrString", + "StructPtrHeadStringPtrString", + "StructPtrHeadOmitEmptyStringPtrString", + "StructHeadNumberPtrString", + "StructHeadOmitEmptyNumberPtrString", + "StructPtrHeadNumberPtrString", + "StructPtrHeadOmitEmptyNumberPtrString", + "StructHead", + "StructHeadOmitEmpty", + "StructPtrHead", + "StructPtrHeadOmitEmpty", + "StructFieldInt", + "StructFieldOmitEmptyInt", + "StructEndInt", + "StructEndOmitEmptyInt", + "StructFieldUint", + "StructFieldOmitEmptyUint", + "StructEndUint", + "StructEndOmitEmptyUint", + "StructFieldFloat32", + "StructFieldOmitEmptyFloat32", + "StructEndFloat32", + "StructEndOmitEmptyFloat32", + "StructFieldFloat64", + "StructFieldOmitEmptyFloat64", + "StructEndFloat64", + "StructEndOmitEmptyFloat64", + "StructFieldBool", + "StructFieldOmitEmptyBool", + "StructEndBool", + "StructEndOmitEmptyBool", + "StructFieldString", + "StructFieldOmitEmptyString", + "StructEndString", + "StructEndOmitEmptyString", + "StructFieldBytes", + "StructFieldOmitEmptyBytes", + "StructEndBytes", + "StructEndOmitEmptyBytes", + "StructFieldNumber", + "StructFieldOmitEmptyNumber", + "StructEndNumber", + "StructEndOmitEmptyNumber", + "StructFieldArray", + "StructFieldOmitEmptyArray", + "StructEndArray", + "StructEndOmitEmptyArray", + "StructFieldMap", + "StructFieldOmitEmptyMap", + "StructEndMap", + "StructEndOmitEmptyMap", + "StructFieldSlice", + "StructFieldOmitEmptySlice", + "StructEndSlice", + "StructEndOmitEmptySlice", + "StructFieldStruct", + "StructFieldOmitEmptyStruct", + "StructEndStruct", + "StructEndOmitEmptyStruct", + "StructFieldMarshalJSON", + "StructFieldOmitEmptyMarshalJSON", + "StructEndMarshalJSON", + "StructEndOmitEmptyMarshalJSON", + "StructFieldMarshalText", + "StructFieldOmitEmptyMarshalText", + "StructEndMarshalText", + "StructEndOmitEmptyMarshalText", + "StructFieldIntString", + "StructFieldOmitEmptyIntString", + "StructEndIntString", + "StructEndOmitEmptyIntString", + "StructFieldUintString", + "StructFieldOmitEmptyUintString", + "StructEndUintString", + "StructEndOmitEmptyUintString", + "StructFieldFloat32String", + "StructFieldOmitEmptyFloat32String", + "StructEndFloat32String", + "StructEndOmitEmptyFloat32String", + "StructFieldFloat64String", + "StructFieldOmitEmptyFloat64String", + "StructEndFloat64String", + "StructEndOmitEmptyFloat64String", + "StructFieldBoolString", + "StructFieldOmitEmptyBoolString", + "StructEndBoolString", + "StructEndOmitEmptyBoolString", + "StructFieldStringString", + "StructFieldOmitEmptyStringString", + "StructEndStringString", + "StructEndOmitEmptyStringString", + "StructFieldNumberString", + "StructFieldOmitEmptyNumberString", + "StructEndNumberString", + "StructEndOmitEmptyNumberString", + "StructFieldIntPtr", + "StructFieldOmitEmptyIntPtr", + "StructEndIntPtr", + "StructEndOmitEmptyIntPtr", + "StructFieldUintPtr", + "StructFieldOmitEmptyUintPtr", + "StructEndUintPtr", + "StructEndOmitEmptyUintPtr", + "StructFieldFloat32Ptr", + "StructFieldOmitEmptyFloat32Ptr", + "StructEndFloat32Ptr", + "StructEndOmitEmptyFloat32Ptr", + "StructFieldFloat64Ptr", + "StructFieldOmitEmptyFloat64Ptr", + "StructEndFloat64Ptr", + "StructEndOmitEmptyFloat64Ptr", + "StructFieldBoolPtr", + "StructFieldOmitEmptyBoolPtr", + "StructEndBoolPtr", + "StructEndOmitEmptyBoolPtr", + "StructFieldStringPtr", + "StructFieldOmitEmptyStringPtr", + "StructEndStringPtr", + "StructEndOmitEmptyStringPtr", + "StructFieldBytesPtr", + "StructFieldOmitEmptyBytesPtr", + "StructEndBytesPtr", + "StructEndOmitEmptyBytesPtr", + "StructFieldNumberPtr", + "StructFieldOmitEmptyNumberPtr", + "StructEndNumberPtr", + "StructEndOmitEmptyNumberPtr", + "StructFieldArrayPtr", + "StructFieldOmitEmptyArrayPtr", + "StructEndArrayPtr", + "StructEndOmitEmptyArrayPtr", + "StructFieldMapPtr", + "StructFieldOmitEmptyMapPtr", + "StructEndMapPtr", + "StructEndOmitEmptyMapPtr", + "StructFieldSlicePtr", + "StructFieldOmitEmptySlicePtr", + "StructEndSlicePtr", + "StructEndOmitEmptySlicePtr", + "StructFieldMarshalJSONPtr", + "StructFieldOmitEmptyMarshalJSONPtr", + "StructEndMarshalJSONPtr", + "StructEndOmitEmptyMarshalJSONPtr", + "StructFieldMarshalTextPtr", + "StructFieldOmitEmptyMarshalTextPtr", + "StructEndMarshalTextPtr", + "StructEndOmitEmptyMarshalTextPtr", + "StructFieldInterfacePtr", + "StructFieldOmitEmptyInterfacePtr", + "StructEndInterfacePtr", + "StructEndOmitEmptyInterfacePtr", + "StructFieldIntPtrString", + "StructFieldOmitEmptyIntPtrString", + "StructEndIntPtrString", + "StructEndOmitEmptyIntPtrString", + "StructFieldUintPtrString", + "StructFieldOmitEmptyUintPtrString", + "StructEndUintPtrString", + "StructEndOmitEmptyUintPtrString", + "StructFieldFloat32PtrString", + "StructFieldOmitEmptyFloat32PtrString", + "StructEndFloat32PtrString", + "StructEndOmitEmptyFloat32PtrString", + "StructFieldFloat64PtrString", + "StructFieldOmitEmptyFloat64PtrString", + "StructEndFloat64PtrString", + "StructEndOmitEmptyFloat64PtrString", + "StructFieldBoolPtrString", + "StructFieldOmitEmptyBoolPtrString", + "StructEndBoolPtrString", + "StructEndOmitEmptyBoolPtrString", + "StructFieldStringPtrString", + "StructFieldOmitEmptyStringPtrString", + "StructEndStringPtrString", + "StructEndOmitEmptyStringPtrString", + "StructFieldNumberPtrString", + "StructFieldOmitEmptyNumberPtrString", + "StructEndNumberPtrString", + "StructEndOmitEmptyNumberPtrString", + "StructField", + "StructFieldOmitEmpty", + "StructEnd", + "StructEndOmitEmpty", +} + +type OpType uint16 + +const ( + OpEnd OpType = 0 + OpInterface OpType = 1 + OpPtr OpType = 2 + OpSliceElem OpType = 3 + OpSliceEnd OpType = 4 + OpArrayElem OpType = 5 + OpArrayEnd OpType = 6 + OpMapKey OpType = 7 + OpMapValue OpType = 8 + OpMapEnd OpType = 9 + OpRecursive OpType = 10 + OpRecursivePtr OpType = 11 + OpRecursiveEnd OpType = 12 + OpInterfaceEnd OpType = 13 + OpInt OpType = 14 + OpUint OpType = 15 + OpFloat32 OpType = 16 + OpFloat64 OpType = 17 + OpBool OpType = 18 + OpString OpType = 19 + OpBytes OpType = 20 + OpNumber OpType = 21 + OpArray OpType = 22 + OpMap OpType = 23 + OpSlice OpType = 24 + OpStruct OpType = 25 + OpMarshalJSON OpType = 26 + OpMarshalText OpType = 27 + OpIntString OpType = 28 + OpUintString OpType = 29 + OpFloat32String OpType = 30 + OpFloat64String OpType = 31 + OpBoolString OpType = 32 + OpStringString OpType = 33 + OpNumberString OpType = 34 + OpIntPtr OpType = 35 + OpUintPtr OpType = 36 + OpFloat32Ptr OpType = 37 + OpFloat64Ptr OpType = 38 + OpBoolPtr OpType = 39 + OpStringPtr OpType = 40 + OpBytesPtr OpType = 41 + OpNumberPtr OpType = 42 + OpArrayPtr OpType = 43 + OpMapPtr OpType = 44 + OpSlicePtr OpType = 45 + OpMarshalJSONPtr OpType = 46 + OpMarshalTextPtr OpType = 47 + OpInterfacePtr OpType = 48 + OpIntPtrString OpType = 49 + OpUintPtrString OpType = 50 + OpFloat32PtrString OpType = 51 + OpFloat64PtrString OpType = 52 + OpBoolPtrString OpType = 53 + OpStringPtrString OpType = 54 + OpNumberPtrString OpType = 55 + OpStructHeadInt OpType = 56 + OpStructHeadOmitEmptyInt OpType = 57 + OpStructPtrHeadInt OpType = 58 + OpStructPtrHeadOmitEmptyInt OpType = 59 + OpStructHeadUint OpType = 60 + OpStructHeadOmitEmptyUint OpType = 61 + OpStructPtrHeadUint OpType = 62 + OpStructPtrHeadOmitEmptyUint OpType = 63 + OpStructHeadFloat32 OpType = 64 + OpStructHeadOmitEmptyFloat32 OpType = 65 + OpStructPtrHeadFloat32 OpType = 66 + OpStructPtrHeadOmitEmptyFloat32 OpType = 67 + OpStructHeadFloat64 OpType = 68 + OpStructHeadOmitEmptyFloat64 OpType = 69 + OpStructPtrHeadFloat64 OpType = 70 + OpStructPtrHeadOmitEmptyFloat64 OpType = 71 + OpStructHeadBool OpType = 72 + OpStructHeadOmitEmptyBool OpType = 73 + OpStructPtrHeadBool OpType = 74 + OpStructPtrHeadOmitEmptyBool OpType = 75 + OpStructHeadString OpType = 76 + OpStructHeadOmitEmptyString OpType = 77 + OpStructPtrHeadString OpType = 78 + OpStructPtrHeadOmitEmptyString OpType = 79 + OpStructHeadBytes OpType = 80 + OpStructHeadOmitEmptyBytes OpType = 81 + OpStructPtrHeadBytes OpType = 82 + OpStructPtrHeadOmitEmptyBytes OpType = 83 + OpStructHeadNumber OpType = 84 + OpStructHeadOmitEmptyNumber OpType = 85 + OpStructPtrHeadNumber OpType = 86 + OpStructPtrHeadOmitEmptyNumber OpType = 87 + OpStructHeadArray OpType = 88 + OpStructHeadOmitEmptyArray OpType = 89 + OpStructPtrHeadArray OpType = 90 + OpStructPtrHeadOmitEmptyArray OpType = 91 + OpStructHeadMap OpType = 92 + OpStructHeadOmitEmptyMap OpType = 93 + OpStructPtrHeadMap OpType = 94 + OpStructPtrHeadOmitEmptyMap OpType = 95 + OpStructHeadSlice OpType = 96 + OpStructHeadOmitEmptySlice OpType = 97 + OpStructPtrHeadSlice OpType = 98 + OpStructPtrHeadOmitEmptySlice OpType = 99 + OpStructHeadStruct OpType = 100 + OpStructHeadOmitEmptyStruct OpType = 101 + OpStructPtrHeadStruct OpType = 102 + OpStructPtrHeadOmitEmptyStruct OpType = 103 + OpStructHeadMarshalJSON OpType = 104 + OpStructHeadOmitEmptyMarshalJSON OpType = 105 + OpStructPtrHeadMarshalJSON OpType = 106 + OpStructPtrHeadOmitEmptyMarshalJSON OpType = 107 + OpStructHeadMarshalText OpType = 108 + OpStructHeadOmitEmptyMarshalText OpType = 109 + OpStructPtrHeadMarshalText OpType = 110 + OpStructPtrHeadOmitEmptyMarshalText OpType = 111 + OpStructHeadIntString OpType = 112 + OpStructHeadOmitEmptyIntString OpType = 113 + OpStructPtrHeadIntString OpType = 114 + OpStructPtrHeadOmitEmptyIntString OpType = 115 + OpStructHeadUintString OpType = 116 + OpStructHeadOmitEmptyUintString OpType = 117 + OpStructPtrHeadUintString OpType = 118 + OpStructPtrHeadOmitEmptyUintString OpType = 119 + OpStructHeadFloat32String OpType = 120 + OpStructHeadOmitEmptyFloat32String OpType = 121 + OpStructPtrHeadFloat32String OpType = 122 + OpStructPtrHeadOmitEmptyFloat32String OpType = 123 + OpStructHeadFloat64String OpType = 124 + OpStructHeadOmitEmptyFloat64String OpType = 125 + OpStructPtrHeadFloat64String OpType = 126 + OpStructPtrHeadOmitEmptyFloat64String OpType = 127 + OpStructHeadBoolString OpType = 128 + OpStructHeadOmitEmptyBoolString OpType = 129 + OpStructPtrHeadBoolString OpType = 130 + OpStructPtrHeadOmitEmptyBoolString OpType = 131 + OpStructHeadStringString OpType = 132 + OpStructHeadOmitEmptyStringString OpType = 133 + OpStructPtrHeadStringString OpType = 134 + OpStructPtrHeadOmitEmptyStringString OpType = 135 + OpStructHeadNumberString OpType = 136 + OpStructHeadOmitEmptyNumberString OpType = 137 + OpStructPtrHeadNumberString OpType = 138 + OpStructPtrHeadOmitEmptyNumberString OpType = 139 + OpStructHeadIntPtr OpType = 140 + OpStructHeadOmitEmptyIntPtr OpType = 141 + OpStructPtrHeadIntPtr OpType = 142 + OpStructPtrHeadOmitEmptyIntPtr OpType = 143 + OpStructHeadUintPtr OpType = 144 + OpStructHeadOmitEmptyUintPtr OpType = 145 + OpStructPtrHeadUintPtr OpType = 146 + OpStructPtrHeadOmitEmptyUintPtr OpType = 147 + OpStructHeadFloat32Ptr OpType = 148 + OpStructHeadOmitEmptyFloat32Ptr OpType = 149 + OpStructPtrHeadFloat32Ptr OpType = 150 + OpStructPtrHeadOmitEmptyFloat32Ptr OpType = 151 + OpStructHeadFloat64Ptr OpType = 152 + OpStructHeadOmitEmptyFloat64Ptr OpType = 153 + OpStructPtrHeadFloat64Ptr OpType = 154 + OpStructPtrHeadOmitEmptyFloat64Ptr OpType = 155 + OpStructHeadBoolPtr OpType = 156 + OpStructHeadOmitEmptyBoolPtr OpType = 157 + OpStructPtrHeadBoolPtr OpType = 158 + OpStructPtrHeadOmitEmptyBoolPtr OpType = 159 + OpStructHeadStringPtr OpType = 160 + OpStructHeadOmitEmptyStringPtr OpType = 161 + OpStructPtrHeadStringPtr OpType = 162 + OpStructPtrHeadOmitEmptyStringPtr OpType = 163 + OpStructHeadBytesPtr OpType = 164 + OpStructHeadOmitEmptyBytesPtr OpType = 165 + OpStructPtrHeadBytesPtr OpType = 166 + OpStructPtrHeadOmitEmptyBytesPtr OpType = 167 + OpStructHeadNumberPtr OpType = 168 + OpStructHeadOmitEmptyNumberPtr OpType = 169 + OpStructPtrHeadNumberPtr OpType = 170 + OpStructPtrHeadOmitEmptyNumberPtr OpType = 171 + OpStructHeadArrayPtr OpType = 172 + OpStructHeadOmitEmptyArrayPtr OpType = 173 + OpStructPtrHeadArrayPtr OpType = 174 + OpStructPtrHeadOmitEmptyArrayPtr OpType = 175 + OpStructHeadMapPtr OpType = 176 + OpStructHeadOmitEmptyMapPtr OpType = 177 + OpStructPtrHeadMapPtr OpType = 178 + OpStructPtrHeadOmitEmptyMapPtr OpType = 179 + OpStructHeadSlicePtr OpType = 180 + OpStructHeadOmitEmptySlicePtr OpType = 181 + OpStructPtrHeadSlicePtr OpType = 182 + OpStructPtrHeadOmitEmptySlicePtr OpType = 183 + OpStructHeadMarshalJSONPtr OpType = 184 + OpStructHeadOmitEmptyMarshalJSONPtr OpType = 185 + OpStructPtrHeadMarshalJSONPtr OpType = 186 + OpStructPtrHeadOmitEmptyMarshalJSONPtr OpType = 187 + OpStructHeadMarshalTextPtr OpType = 188 + OpStructHeadOmitEmptyMarshalTextPtr OpType = 189 + OpStructPtrHeadMarshalTextPtr OpType = 190 + OpStructPtrHeadOmitEmptyMarshalTextPtr OpType = 191 + OpStructHeadInterfacePtr OpType = 192 + OpStructHeadOmitEmptyInterfacePtr OpType = 193 + OpStructPtrHeadInterfacePtr OpType = 194 + OpStructPtrHeadOmitEmptyInterfacePtr OpType = 195 + OpStructHeadIntPtrString OpType = 196 + OpStructHeadOmitEmptyIntPtrString OpType = 197 + OpStructPtrHeadIntPtrString OpType = 198 + OpStructPtrHeadOmitEmptyIntPtrString OpType = 199 + OpStructHeadUintPtrString OpType = 200 + OpStructHeadOmitEmptyUintPtrString OpType = 201 + OpStructPtrHeadUintPtrString OpType = 202 + OpStructPtrHeadOmitEmptyUintPtrString OpType = 203 + OpStructHeadFloat32PtrString OpType = 204 + OpStructHeadOmitEmptyFloat32PtrString OpType = 205 + OpStructPtrHeadFloat32PtrString OpType = 206 + OpStructPtrHeadOmitEmptyFloat32PtrString OpType = 207 + OpStructHeadFloat64PtrString OpType = 208 + OpStructHeadOmitEmptyFloat64PtrString OpType = 209 + OpStructPtrHeadFloat64PtrString OpType = 210 + OpStructPtrHeadOmitEmptyFloat64PtrString OpType = 211 + OpStructHeadBoolPtrString OpType = 212 + OpStructHeadOmitEmptyBoolPtrString OpType = 213 + OpStructPtrHeadBoolPtrString OpType = 214 + OpStructPtrHeadOmitEmptyBoolPtrString OpType = 215 + OpStructHeadStringPtrString OpType = 216 + OpStructHeadOmitEmptyStringPtrString OpType = 217 + OpStructPtrHeadStringPtrString OpType = 218 + OpStructPtrHeadOmitEmptyStringPtrString OpType = 219 + OpStructHeadNumberPtrString OpType = 220 + OpStructHeadOmitEmptyNumberPtrString OpType = 221 + OpStructPtrHeadNumberPtrString OpType = 222 + OpStructPtrHeadOmitEmptyNumberPtrString OpType = 223 + OpStructHead OpType = 224 + OpStructHeadOmitEmpty OpType = 225 + OpStructPtrHead OpType = 226 + OpStructPtrHeadOmitEmpty OpType = 227 + OpStructFieldInt OpType = 228 + OpStructFieldOmitEmptyInt OpType = 229 + OpStructEndInt OpType = 230 + OpStructEndOmitEmptyInt OpType = 231 + OpStructFieldUint OpType = 232 + OpStructFieldOmitEmptyUint OpType = 233 + OpStructEndUint OpType = 234 + OpStructEndOmitEmptyUint OpType = 235 + OpStructFieldFloat32 OpType = 236 + OpStructFieldOmitEmptyFloat32 OpType = 237 + OpStructEndFloat32 OpType = 238 + OpStructEndOmitEmptyFloat32 OpType = 239 + OpStructFieldFloat64 OpType = 240 + OpStructFieldOmitEmptyFloat64 OpType = 241 + OpStructEndFloat64 OpType = 242 + OpStructEndOmitEmptyFloat64 OpType = 243 + OpStructFieldBool OpType = 244 + OpStructFieldOmitEmptyBool OpType = 245 + OpStructEndBool OpType = 246 + OpStructEndOmitEmptyBool OpType = 247 + OpStructFieldString OpType = 248 + OpStructFieldOmitEmptyString OpType = 249 + OpStructEndString OpType = 250 + OpStructEndOmitEmptyString OpType = 251 + OpStructFieldBytes OpType = 252 + OpStructFieldOmitEmptyBytes OpType = 253 + OpStructEndBytes OpType = 254 + OpStructEndOmitEmptyBytes OpType = 255 + OpStructFieldNumber OpType = 256 + OpStructFieldOmitEmptyNumber OpType = 257 + OpStructEndNumber OpType = 258 + OpStructEndOmitEmptyNumber OpType = 259 + OpStructFieldArray OpType = 260 + OpStructFieldOmitEmptyArray OpType = 261 + OpStructEndArray OpType = 262 + OpStructEndOmitEmptyArray OpType = 263 + OpStructFieldMap OpType = 264 + OpStructFieldOmitEmptyMap OpType = 265 + OpStructEndMap OpType = 266 + OpStructEndOmitEmptyMap OpType = 267 + OpStructFieldSlice OpType = 268 + OpStructFieldOmitEmptySlice OpType = 269 + OpStructEndSlice OpType = 270 + OpStructEndOmitEmptySlice OpType = 271 + OpStructFieldStruct OpType = 272 + OpStructFieldOmitEmptyStruct OpType = 273 + OpStructEndStruct OpType = 274 + OpStructEndOmitEmptyStruct OpType = 275 + OpStructFieldMarshalJSON OpType = 276 + OpStructFieldOmitEmptyMarshalJSON OpType = 277 + OpStructEndMarshalJSON OpType = 278 + OpStructEndOmitEmptyMarshalJSON OpType = 279 + OpStructFieldMarshalText OpType = 280 + OpStructFieldOmitEmptyMarshalText OpType = 281 + OpStructEndMarshalText OpType = 282 + OpStructEndOmitEmptyMarshalText OpType = 283 + OpStructFieldIntString OpType = 284 + OpStructFieldOmitEmptyIntString OpType = 285 + OpStructEndIntString OpType = 286 + OpStructEndOmitEmptyIntString OpType = 287 + OpStructFieldUintString OpType = 288 + OpStructFieldOmitEmptyUintString OpType = 289 + OpStructEndUintString OpType = 290 + OpStructEndOmitEmptyUintString OpType = 291 + OpStructFieldFloat32String OpType = 292 + OpStructFieldOmitEmptyFloat32String OpType = 293 + OpStructEndFloat32String OpType = 294 + OpStructEndOmitEmptyFloat32String OpType = 295 + OpStructFieldFloat64String OpType = 296 + OpStructFieldOmitEmptyFloat64String OpType = 297 + OpStructEndFloat64String OpType = 298 + OpStructEndOmitEmptyFloat64String OpType = 299 + OpStructFieldBoolString OpType = 300 + OpStructFieldOmitEmptyBoolString OpType = 301 + OpStructEndBoolString OpType = 302 + OpStructEndOmitEmptyBoolString OpType = 303 + OpStructFieldStringString OpType = 304 + OpStructFieldOmitEmptyStringString OpType = 305 + OpStructEndStringString OpType = 306 + OpStructEndOmitEmptyStringString OpType = 307 + OpStructFieldNumberString OpType = 308 + OpStructFieldOmitEmptyNumberString OpType = 309 + OpStructEndNumberString OpType = 310 + OpStructEndOmitEmptyNumberString OpType = 311 + OpStructFieldIntPtr OpType = 312 + OpStructFieldOmitEmptyIntPtr OpType = 313 + OpStructEndIntPtr OpType = 314 + OpStructEndOmitEmptyIntPtr OpType = 315 + OpStructFieldUintPtr OpType = 316 + OpStructFieldOmitEmptyUintPtr OpType = 317 + OpStructEndUintPtr OpType = 318 + OpStructEndOmitEmptyUintPtr OpType = 319 + OpStructFieldFloat32Ptr OpType = 320 + OpStructFieldOmitEmptyFloat32Ptr OpType = 321 + OpStructEndFloat32Ptr OpType = 322 + OpStructEndOmitEmptyFloat32Ptr OpType = 323 + OpStructFieldFloat64Ptr OpType = 324 + OpStructFieldOmitEmptyFloat64Ptr OpType = 325 + OpStructEndFloat64Ptr OpType = 326 + OpStructEndOmitEmptyFloat64Ptr OpType = 327 + OpStructFieldBoolPtr OpType = 328 + OpStructFieldOmitEmptyBoolPtr OpType = 329 + OpStructEndBoolPtr OpType = 330 + OpStructEndOmitEmptyBoolPtr OpType = 331 + OpStructFieldStringPtr OpType = 332 + OpStructFieldOmitEmptyStringPtr OpType = 333 + OpStructEndStringPtr OpType = 334 + OpStructEndOmitEmptyStringPtr OpType = 335 + OpStructFieldBytesPtr OpType = 336 + OpStructFieldOmitEmptyBytesPtr OpType = 337 + OpStructEndBytesPtr OpType = 338 + OpStructEndOmitEmptyBytesPtr OpType = 339 + OpStructFieldNumberPtr OpType = 340 + OpStructFieldOmitEmptyNumberPtr OpType = 341 + OpStructEndNumberPtr OpType = 342 + OpStructEndOmitEmptyNumberPtr OpType = 343 + OpStructFieldArrayPtr OpType = 344 + OpStructFieldOmitEmptyArrayPtr OpType = 345 + OpStructEndArrayPtr OpType = 346 + OpStructEndOmitEmptyArrayPtr OpType = 347 + OpStructFieldMapPtr OpType = 348 + OpStructFieldOmitEmptyMapPtr OpType = 349 + OpStructEndMapPtr OpType = 350 + OpStructEndOmitEmptyMapPtr OpType = 351 + OpStructFieldSlicePtr OpType = 352 + OpStructFieldOmitEmptySlicePtr OpType = 353 + OpStructEndSlicePtr OpType = 354 + OpStructEndOmitEmptySlicePtr OpType = 355 + OpStructFieldMarshalJSONPtr OpType = 356 + OpStructFieldOmitEmptyMarshalJSONPtr OpType = 357 + OpStructEndMarshalJSONPtr OpType = 358 + OpStructEndOmitEmptyMarshalJSONPtr OpType = 359 + OpStructFieldMarshalTextPtr OpType = 360 + OpStructFieldOmitEmptyMarshalTextPtr OpType = 361 + OpStructEndMarshalTextPtr OpType = 362 + OpStructEndOmitEmptyMarshalTextPtr OpType = 363 + OpStructFieldInterfacePtr OpType = 364 + OpStructFieldOmitEmptyInterfacePtr OpType = 365 + OpStructEndInterfacePtr OpType = 366 + OpStructEndOmitEmptyInterfacePtr OpType = 367 + OpStructFieldIntPtrString OpType = 368 + OpStructFieldOmitEmptyIntPtrString OpType = 369 + OpStructEndIntPtrString OpType = 370 + OpStructEndOmitEmptyIntPtrString OpType = 371 + OpStructFieldUintPtrString OpType = 372 + OpStructFieldOmitEmptyUintPtrString OpType = 373 + OpStructEndUintPtrString OpType = 374 + OpStructEndOmitEmptyUintPtrString OpType = 375 + OpStructFieldFloat32PtrString OpType = 376 + OpStructFieldOmitEmptyFloat32PtrString OpType = 377 + OpStructEndFloat32PtrString OpType = 378 + OpStructEndOmitEmptyFloat32PtrString OpType = 379 + OpStructFieldFloat64PtrString OpType = 380 + OpStructFieldOmitEmptyFloat64PtrString OpType = 381 + OpStructEndFloat64PtrString OpType = 382 + OpStructEndOmitEmptyFloat64PtrString OpType = 383 + OpStructFieldBoolPtrString OpType = 384 + OpStructFieldOmitEmptyBoolPtrString OpType = 385 + OpStructEndBoolPtrString OpType = 386 + OpStructEndOmitEmptyBoolPtrString OpType = 387 + OpStructFieldStringPtrString OpType = 388 + OpStructFieldOmitEmptyStringPtrString OpType = 389 + OpStructEndStringPtrString OpType = 390 + OpStructEndOmitEmptyStringPtrString OpType = 391 + OpStructFieldNumberPtrString OpType = 392 + OpStructFieldOmitEmptyNumberPtrString OpType = 393 + OpStructEndNumberPtrString OpType = 394 + OpStructEndOmitEmptyNumberPtrString OpType = 395 + OpStructField OpType = 396 + OpStructFieldOmitEmpty OpType = 397 + OpStructEnd OpType = 398 + OpStructEndOmitEmpty OpType = 399 +) + +func (t OpType) String() string { + if int(t) >= 400 { + return "" + } + return opTypeStrings[int(t)] +} + +func (t OpType) CodeType() CodeType { + if strings.Contains(t.String(), "Struct") { + if strings.Contains(t.String(), "End") { + return CodeStructEnd + } + return CodeStructField + } + switch t { + case OpArray, OpArrayPtr: + return CodeArrayHead + case OpArrayElem: + return CodeArrayElem + case OpSlice, OpSlicePtr: + return CodeSliceHead + case OpSliceElem: + return CodeSliceElem + case OpMap, OpMapPtr: + return CodeMapHead + case OpMapKey: + return CodeMapKey + case OpMapValue: + return CodeMapValue + case OpMapEnd: + return CodeMapEnd + } + + return CodeOp +} + +func (t OpType) HeadToPtrHead() OpType { + if strings.Index(t.String(), "PtrHead") > 0 { + return t + } + + idx := strings.Index(t.String(), "Head") + if idx == -1 { + return t + } + suffix := "PtrHead" + t.String()[idx+len("Head"):] + + const toPtrOffset = 2 + if strings.Contains(OpType(int(t)+toPtrOffset).String(), suffix) { + return OpType(int(t) + toPtrOffset) + } + return t +} + +func (t OpType) HeadToOmitEmptyHead() OpType { + const toOmitEmptyOffset = 1 + if strings.Contains(OpType(int(t)+toOmitEmptyOffset).String(), "OmitEmpty") { + return OpType(int(t) + toOmitEmptyOffset) + } + + return t +} + +func (t OpType) PtrHeadToHead() OpType { + idx := strings.Index(t.String(), "PtrHead") + if idx == -1 { + return t + } + suffix := t.String()[idx+len("Ptr"):] + + const toPtrOffset = 2 + if strings.Contains(OpType(int(t)-toPtrOffset).String(), suffix) { + return OpType(int(t) - toPtrOffset) + } + return t +} + +func (t OpType) FieldToEnd() OpType { + idx := strings.Index(t.String(), "Field") + if idx == -1 { + return t + } + suffix := t.String()[idx+len("Field"):] + if suffix == "" || suffix == "OmitEmpty" { + return t + } + const toEndOffset = 2 + if strings.Contains(OpType(int(t)+toEndOffset).String(), "End"+suffix) { + return OpType(int(t) + toEndOffset) + } + return t +} + +func (t OpType) FieldToOmitEmptyField() OpType { + const toOmitEmptyOffset = 1 + if strings.Contains(OpType(int(t)+toOmitEmptyOffset).String(), "OmitEmpty") { + return OpType(int(t) + toOmitEmptyOffset) + } + return t +} diff --git a/vendor/github.com/goccy/go-json/internal/encoder/query.go b/vendor/github.com/goccy/go-json/internal/encoder/query.go new file mode 100644 index 000000000..1e1850cc1 --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/encoder/query.go @@ -0,0 +1,135 @@ +package encoder + +import ( + "context" + "fmt" + "reflect" +) + +var ( + Marshal func(interface{}) ([]byte, error) + Unmarshal func([]byte, interface{}) error +) + +type FieldQuery struct { + Name string + Fields []*FieldQuery + hash string +} + +func (q *FieldQuery) Hash() string { + if q.hash != "" { + return q.hash + } + b, _ := Marshal(q) + q.hash = string(b) + return q.hash +} + +func (q *FieldQuery) MarshalJSON() ([]byte, error) { + if q.Name != "" { + if len(q.Fields) > 0 { + return Marshal(map[string][]*FieldQuery{q.Name: q.Fields}) + } + return Marshal(q.Name) + } + return Marshal(q.Fields) +} + +func (q *FieldQuery) QueryString() (FieldQueryString, error) { + b, err := Marshal(q) + if err != nil { + return "", err + } + return FieldQueryString(b), nil +} + +type FieldQueryString string + +func (s FieldQueryString) Build() (*FieldQuery, error) { + var query interface{} + if err := Unmarshal([]byte(s), &query); err != nil { + return nil, err + } + return s.build(reflect.ValueOf(query)) +} + +func (s FieldQueryString) build(v reflect.Value) (*FieldQuery, error) { + switch v.Type().Kind() { + case reflect.String: + return s.buildString(v) + case reflect.Map: + return s.buildMap(v) + case reflect.Slice: + return s.buildSlice(v) + case reflect.Interface: + return s.build(reflect.ValueOf(v.Interface())) + } + return nil, fmt.Errorf("failed to build field query") +} + +func (s FieldQueryString) buildString(v reflect.Value) (*FieldQuery, error) { + b := []byte(v.String()) + switch b[0] { + case '[', '{': + var query interface{} + if err := Unmarshal(b, &query); err != nil { + return nil, err + } + if str, ok := query.(string); ok { + return &FieldQuery{Name: str}, nil + } + return s.build(reflect.ValueOf(query)) + } + return &FieldQuery{Name: string(b)}, nil +} + +func (s FieldQueryString) buildSlice(v reflect.Value) (*FieldQuery, error) { + fields := make([]*FieldQuery, 0, v.Len()) + for i := 0; i < v.Len(); i++ { + def, err := s.build(v.Index(i)) + if err != nil { + return nil, err + } + fields = append(fields, def) + } + return &FieldQuery{Fields: fields}, nil +} + +func (s FieldQueryString) buildMap(v reflect.Value) (*FieldQuery, error) { + keys := v.MapKeys() + if len(keys) != 1 { + return nil, fmt.Errorf("failed to build field query object") + } + key := keys[0] + if key.Type().Kind() != reflect.String { + return nil, fmt.Errorf("failed to build field query. invalid object key type") + } + name := key.String() + def, err := s.build(v.MapIndex(key)) + if err != nil { + return nil, err + } + return &FieldQuery{ + Name: name, + Fields: def.Fields, + }, nil +} + +type queryKey struct{} + +func FieldQueryFromContext(ctx context.Context) *FieldQuery { + query := ctx.Value(queryKey{}) + if query == nil { + return nil + } + q, ok := query.(*FieldQuery) + if !ok { + return nil + } + return q +} + +func SetFieldQueryToContext(ctx context.Context, query *FieldQuery) context.Context { + return context.WithValue(ctx, queryKey{}, query) +} diff --git a/vendor/github.com/goccy/go-json/internal/encoder/string.go b/vendor/github.com/goccy/go-json/internal/encoder/string.go new file mode 100644 index 000000000..e4152b27c --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/encoder/string.go @@ -0,0 +1,459 @@ +package encoder + +import ( + "math/bits" + "reflect" + "unsafe" +) + +const ( + lsb = 0x0101010101010101 + msb = 0x8080808080808080 +) + +var hex = "0123456789abcdef" + +//nolint:govet +func stringToUint64Slice(s string) []uint64 { + return *(*[]uint64)(unsafe.Pointer(&reflect.SliceHeader{ + Data: ((*reflect.StringHeader)(unsafe.Pointer(&s))).Data, + Len: len(s) / 8, + Cap: len(s) / 8, + })) +} + +func AppendString(ctx *RuntimeContext, buf []byte, s string) []byte { + if ctx.Option.Flag&HTMLEscapeOption != 0 { + if ctx.Option.Flag&NormalizeUTF8Option != 0 { + return appendNormalizedHTMLString(buf, s) + } + return appendHTMLString(buf, s) + } + if ctx.Option.Flag&NormalizeUTF8Option != 0 { + return appendNormalizedString(buf, s) + } + return appendString(buf, s) +} + +func appendNormalizedHTMLString(buf []byte, s string) []byte { + valLen := len(s) + if valLen == 0 { + return append(buf, `""`...) + } + buf = append(buf, '"') + var ( + i, j int + ) + if valLen >= 8 { + chunks := stringToUint64Slice(s) + for _, n := range chunks { + // combine masks before checking for the MSB of each byte. We include + // `n` in the mask to check whether any of the *input* byte MSBs were + // set (i.e. the byte was outside the ASCII range). + mask := n | (n - (lsb * 0x20)) | + ((n ^ (lsb * '"')) - lsb) | + ((n ^ (lsb * '\\')) - lsb) | + ((n ^ (lsb * '<')) - lsb) | + ((n ^ (lsb * '>')) - lsb) | + ((n ^ (lsb * '&')) - lsb) + if (mask & msb) != 0 { + j = bits.TrailingZeros64(mask&msb) / 8 + goto ESCAPE_END + } + } + for i := len(chunks) * 8; i < valLen; i++ { + if needEscapeHTMLNormalizeUTF8[s[i]] { + j = i + goto ESCAPE_END + } + } + // no found any escape characters. + return append(append(buf, s...), '"') + } +ESCAPE_END: + for j < valLen { + c := s[j] + + if !needEscapeHTMLNormalizeUTF8[c] { + // fast path: most of the time, printable ascii characters are used + j++ + continue + } + + switch c { + case '\\', '"': + buf = append(buf, s[i:j]...) + buf = append(buf, '\\', c) + i = j + 1 + j = j + 1 + continue + + case '\n': + buf = append(buf, s[i:j]...) + buf = append(buf, '\\', 'n') + i = j + 1 + j = j + 1 + continue + + case '\r': + buf = append(buf, s[i:j]...) + buf = append(buf, '\\', 'r') + i = j + 1 + j = j + 1 + continue + + case '\t': + buf = append(buf, s[i:j]...) + buf = append(buf, '\\', 't') + i = j + 1 + j = j + 1 + continue + + case '<', '>', '&': + buf = append(buf, s[i:j]...) + buf = append(buf, `\u00`...) + buf = append(buf, hex[c>>4], hex[c&0xF]) + i = j + 1 + j = j + 1 + continue + + case 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0B, 0x0C, 0x0E, 0x0F, // 0x00-0x0F + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F: // 0x10-0x1F + buf = append(buf, s[i:j]...) + buf = append(buf, `\u00`...) + buf = append(buf, hex[c>>4], hex[c&0xF]) + i = j + 1 + j = j + 1 + continue + } + state, size := decodeRuneInString(s[j:]) + switch state { + case runeErrorState: + buf = append(buf, s[i:j]...) + buf = append(buf, `\ufffd`...) + i = j + 1 + j = j + 1 + continue + // U+2028 is LINE SEPARATOR. + // U+2029 is PARAGRAPH SEPARATOR. + // They are both technically valid characters in JSON strings, + // but don't work in JSONP, which has to be evaluated as JavaScript, + // and can lead to security holes there. It is valid JSON to + // escape them, so we do so unconditionally. + // See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion. + case lineSepState: + buf = append(buf, s[i:j]...) + buf = append(buf, `\u2028`...) + i = j + 3 + j = j + 3 + continue + case paragraphSepState: + buf = append(buf, s[i:j]...) + buf = append(buf, `\u2029`...) + i = j + 3 + j = j + 3 + continue + } + j += size + } + + return append(append(buf, s[i:]...), '"') +} + +func appendHTMLString(buf []byte, s string) []byte { + valLen := len(s) + if valLen == 0 { + return append(buf, `""`...) + } + buf = append(buf, '"') + var ( + i, j int + ) + if valLen >= 8 { + chunks := stringToUint64Slice(s) + for _, n := range chunks { + // combine masks before checking for the MSB of each byte. We include + // `n` in the mask to check whether any of the *input* byte MSBs were + // set (i.e. the byte was outside the ASCII range). + mask := n | (n - (lsb * 0x20)) | + ((n ^ (lsb * '"')) - lsb) | + ((n ^ (lsb * '\\')) - lsb) | + ((n ^ (lsb * '<')) - lsb) | + ((n ^ (lsb * '>')) - lsb) | + ((n ^ (lsb * '&')) - lsb) + if (mask & msb) != 0 { + j = bits.TrailingZeros64(mask&msb) / 8 + goto ESCAPE_END + } + } + for i := len(chunks) * 8; i < valLen; i++ { + if needEscapeHTML[s[i]] { + j = i + goto ESCAPE_END + } + } + // no found any escape characters. + return append(append(buf, s...), '"') + } +ESCAPE_END: + for j < valLen { + c := s[j] + + if !needEscapeHTML[c] { + // fast path: most of the time, printable ascii characters are used + j++ + continue + } + + switch c { + case '\\', '"': + buf = append(buf, s[i:j]...) + buf = append(buf, '\\', c) + i = j + 1 + j = j + 1 + continue + + case '\n': + buf = append(buf, s[i:j]...) + buf = append(buf, '\\', 'n') + i = j + 1 + j = j + 1 + continue + + case '\r': + buf = append(buf, s[i:j]...) + buf = append(buf, '\\', 'r') + i = j + 1 + j = j + 1 + continue + + case '\t': + buf = append(buf, s[i:j]...) + buf = append(buf, '\\', 't') + i = j + 1 + j = j + 1 + continue + + case '<', '>', '&': + buf = append(buf, s[i:j]...) + buf = append(buf, `\u00`...) + buf = append(buf, hex[c>>4], hex[c&0xF]) + i = j + 1 + j = j + 1 + continue + + case 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0B, 0x0C, 0x0E, 0x0F, // 0x00-0x0F + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F: // 0x10-0x1F + buf = append(buf, s[i:j]...) + buf = append(buf, `\u00`...) + buf = append(buf, hex[c>>4], hex[c&0xF]) + i = j + 1 + j = j + 1 + continue + } + j++ + } + + return append(append(buf, s[i:]...), '"') +} + +func appendNormalizedString(buf []byte, s string) []byte { + valLen := len(s) + if valLen == 0 { + return append(buf, `""`...) + } + buf = append(buf, '"') + var ( + i, j int + ) + if valLen >= 8 { + chunks := stringToUint64Slice(s) + for _, n := range chunks { + // combine masks before checking for the MSB of each byte. We include + // `n` in the mask to check whether any of the *input* byte MSBs were + // set (i.e. the byte was outside the ASCII range). + mask := n | (n - (lsb * 0x20)) | + ((n ^ (lsb * '"')) - lsb) | + ((n ^ (lsb * '\\')) - lsb) + if (mask & msb) != 0 { + j = bits.TrailingZeros64(mask&msb) / 8 + goto ESCAPE_END + } + } + valLen := len(s) + for i := len(chunks) * 8; i < valLen; i++ { + if needEscapeNormalizeUTF8[s[i]] { + j = i + goto ESCAPE_END + } + } + return append(append(buf, s...), '"') + } +ESCAPE_END: + for j < valLen { + c := s[j] + + if !needEscapeNormalizeUTF8[c] { + // fast path: most of the time, printable ascii characters are used + j++ + continue + } + + switch c { + case '\\', '"': + buf = append(buf, s[i:j]...) + buf = append(buf, '\\', c) + i = j + 1 + j = j + 1 + continue + + case '\n': + buf = append(buf, s[i:j]...) + buf = append(buf, '\\', 'n') + i = j + 1 + j = j + 1 + continue + + case '\r': + buf = append(buf, s[i:j]...) + buf = append(buf, '\\', 'r') + i = j + 1 + j = j + 1 + continue + + case '\t': + buf = append(buf, s[i:j]...) + buf = append(buf, '\\', 't') + i = j + 1 + j = j + 1 + continue + + case 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0B, 0x0C, 0x0E, 0x0F, // 0x00-0x0F + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F: // 0x10-0x1F + buf = append(buf, s[i:j]...) + buf = append(buf, `\u00`...) + buf = append(buf, hex[c>>4], hex[c&0xF]) + i = j + 1 + j = j + 1 + continue + } + + state, size := decodeRuneInString(s[j:]) + switch state { + case runeErrorState: + buf = append(buf, s[i:j]...) + buf = append(buf, `\ufffd`...) + i = j + 1 + j = j + 1 + continue + // U+2028 is LINE SEPARATOR. + // U+2029 is PARAGRAPH SEPARATOR. + // They are both technically valid characters in JSON strings, + // but don't work in JSONP, which has to be evaluated as JavaScript, + // and can lead to security holes there. It is valid JSON to + // escape them, so we do so unconditionally. + // See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion. + case lineSepState: + buf = append(buf, s[i:j]...) + buf = append(buf, `\u2028`...) + i = j + 3 + j = j + 3 + continue + case paragraphSepState: + buf = append(buf, s[i:j]...) + buf = append(buf, `\u2029`...) + i = j + 3 + j = j + 3 + continue + } + j += size + } + + return append(append(buf, s[i:]...), '"') +} + +func appendString(buf []byte, s string) []byte { + valLen := len(s) + if valLen == 0 { + return append(buf, `""`...) + } + buf = append(buf, '"') + var ( + i, j int + ) + if valLen >= 8 { + chunks := stringToUint64Slice(s) + for _, n := range chunks { + // combine masks before checking for the MSB of each byte. We include + // `n` in the mask to check whether any of the *input* byte MSBs were + // set (i.e. the byte was outside the ASCII range). + mask := n | (n - (lsb * 0x20)) | + ((n ^ (lsb * '"')) - lsb) | + ((n ^ (lsb * '\\')) - lsb) + if (mask & msb) != 0 { + j = bits.TrailingZeros64(mask&msb) / 8 + goto ESCAPE_END + } + } + valLen := len(s) + for i := len(chunks) * 8; i < valLen; i++ { + if needEscape[s[i]] { + j = i + goto ESCAPE_END + } + } + return append(append(buf, s...), '"') + } +ESCAPE_END: + for j < valLen { + c := s[j] + + if !needEscape[c] { + // fast path: most of the time, printable ascii characters are used + j++ + continue + } + + switch c { + case '\\', '"': + buf = append(buf, s[i:j]...) + buf = append(buf, '\\', c) + i = j + 1 + j = j + 1 + continue + + case '\n': + buf = append(buf, s[i:j]...) + buf = append(buf, '\\', 'n') + i = j + 1 + j = j + 1 + continue + + case '\r': + buf = append(buf, s[i:j]...) + buf = append(buf, '\\', 'r') + i = j + 1 + j = j + 1 + continue + + case '\t': + buf = append(buf, s[i:j]...) + buf = append(buf, '\\', 't') + i = j + 1 + j = j + 1 + continue + + case 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0B, 0x0C, 0x0E, 0x0F, // 0x00-0x0F + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F: // 0x10-0x1F + buf = append(buf, s[i:j]...) + buf = append(buf, `\u00`...) + buf = append(buf, hex[c>>4], hex[c&0xF]) + i = j + 1 + j = j + 1 + continue + } + j++ + } + + return append(append(buf, s[i:]...), '"') +} diff --git a/vendor/github.com/goccy/go-json/internal/encoder/string_table.go b/vendor/github.com/goccy/go-json/internal/encoder/string_table.go new file mode 100644 index 000000000..ebe42c92d --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/encoder/string_table.go @@ -0,0 +1,415 @@ +package encoder + +var needEscapeHTMLNormalizeUTF8 = [256]bool{ + '"': true, + '&': true, + '<': true, + '>': true, + '\\': true, + 0x00: true, + 0x01: true, + 0x02: true, + 0x03: true, + 0x04: true, + 0x05: true, + 0x06: true, + 0x07: true, + 0x08: true, + 0x09: true, + 0x0a: true, + 0x0b: true, + 0x0c: true, + 0x0d: true, + 0x0e: true, + 0x0f: true, + 0x10: true, + 0x11: true, + 0x12: true, + 0x13: true, + 0x14: true, + 0x15: true, + 0x16: true, + 0x17: true, + 0x18: true, + 0x19: true, + 0x1a: true, + 0x1b: true, + 0x1c: true, + 0x1d: true, + 0x1e: true, + 0x1f: true, + /* 0x20 - 0x7f */ + 0x80: true, + 0x81: true, + 0x82: true, + 0x83: true, + 0x84: true, + 0x85: true, + 0x86: true, + 0x87: true, + 0x88: true, + 0x89: true, + 0x8a: true, + 0x8b: true, + 0x8c: true, + 0x8d: true, + 0x8e: true, + 0x8f: true, + 0x90: true, + 0x91: true, + 0x92: true, + 0x93: true, + 0x94: true, + 0x95: true, + 0x96: true, + 0x97: true, + 0x98: true, + 0x99: true, + 0x9a: true, + 0x9b: true, + 0x9c: true, + 0x9d: true, + 0x9e: true, + 0x9f: true, + 0xa0: true, + 0xa1: true, + 0xa2: true, + 0xa3: true, + 0xa4: true, + 0xa5: true, + 0xa6: true, + 0xa7: true, + 0xa8: true, + 0xa9: true, + 0xaa: true, + 0xab: true, + 0xac: true, + 0xad: true, + 0xae: true, + 0xaf: true, + 0xb0: true, + 0xb1: true, + 0xb2: true, + 0xb3: true, + 0xb4: true, + 0xb5: true, + 0xb6: true, + 0xb7: true, + 0xb8: true, + 0xb9: true, + 0xba: true, + 0xbb: true, + 0xbc: true, + 0xbd: true, + 0xbe: true, + 0xbf: true, + 0xc0: true, + 0xc1: true, + 0xc2: true, + 0xc3: true, + 0xc4: true, + 0xc5: true, + 0xc6: true, + 0xc7: true, + 0xc8: true, + 0xc9: true, + 0xca: true, + 0xcb: true, + 0xcc: true, + 0xcd: true, + 0xce: true, + 0xcf: true, + 0xd0: true, + 0xd1: true, + 0xd2: true, + 0xd3: true, + 0xd4: true, + 0xd5: true, + 0xd6: true, + 0xd7: true, + 0xd8: true, + 0xd9: true, + 0xda: true, + 0xdb: true, + 0xdc: true, + 0xdd: true, + 0xde: true, + 0xdf: true, + 0xe0: true, + 0xe1: true, + 0xe2: true, + 0xe3: true, + 0xe4: true, + 0xe5: true, + 0xe6: true, + 0xe7: true, + 0xe8: true, + 0xe9: true, + 0xea: true, + 0xeb: true, + 0xec: true, + 0xed: true, + 0xee: true, + 0xef: true, + 0xf0: true, + 0xf1: true, + 0xf2: true, + 0xf3: true, + 0xf4: true, + 0xf5: true, + 0xf6: true, + 0xf7: true, + 0xf8: true, + 0xf9: true, + 0xfa: true, + 0xfb: true, + 0xfc: true, + 0xfd: true, + 0xfe: true, + 0xff: true, +} + +var needEscapeNormalizeUTF8 = [256]bool{ + '"': true, + '\\': true, + 0x00: true, + 0x01: true, + 0x02: true, + 0x03: true, + 0x04: true, + 0x05: true, + 0x06: true, + 0x07: true, + 0x08: true, + 0x09: true, + 0x0a: true, + 0x0b: true, + 0x0c: true, + 0x0d: true, + 0x0e: true, + 0x0f: true, + 0x10: true, + 0x11: true, + 0x12: true, + 0x13: true, + 0x14: true, + 0x15: true, + 0x16: true, + 0x17: true, + 0x18: true, + 0x19: true, + 0x1a: true, + 0x1b: true, + 0x1c: true, + 0x1d: true, + 0x1e: true, + 0x1f: true, + /* 0x20 - 0x7f */ + 0x80: true, + 0x81: true, + 0x82: true, + 0x83: true, + 0x84: true, + 0x85: true, + 0x86: true, + 0x87: true, + 0x88: true, + 0x89: true, + 0x8a: true, + 0x8b: true, + 0x8c: true, + 0x8d: true, + 0x8e: true, + 0x8f: true, + 0x90: true, + 0x91: true, + 0x92: true, + 0x93: true, + 0x94: true, + 0x95: true, + 0x96: true, + 0x97: true, + 0x98: true, + 0x99: true, + 0x9a: true, + 0x9b: true, + 0x9c: true, + 0x9d: true, + 0x9e: true, + 0x9f: true, + 0xa0: true, + 0xa1: true, + 0xa2: true, + 0xa3: true, + 0xa4: true, + 0xa5: true, + 0xa6: true, + 0xa7: true, + 0xa8: true, + 0xa9: true, + 0xaa: true, + 0xab: true, + 0xac: true, + 0xad: true, + 0xae: true, + 0xaf: true, + 0xb0: true, + 0xb1: true, + 0xb2: true, + 0xb3: true, + 0xb4: true, + 0xb5: true, + 0xb6: true, + 0xb7: true, + 0xb8: true, + 0xb9: true, + 0xba: true, + 0xbb: true, + 0xbc: true, + 0xbd: true, + 0xbe: true, + 0xbf: true, + 0xc0: true, + 0xc1: true, + 0xc2: true, + 0xc3: true, + 0xc4: true, + 0xc5: true, + 0xc6: true, + 0xc7: true, + 0xc8: true, + 0xc9: true, + 0xca: true, + 0xcb: true, + 0xcc: true, + 0xcd: true, + 0xce: true, + 0xcf: true, + 0xd0: true, + 0xd1: true, + 0xd2: true, + 0xd3: true, + 0xd4: true, + 0xd5: true, + 0xd6: true, + 0xd7: true, + 0xd8: true, + 0xd9: true, + 0xda: true, + 0xdb: true, + 0xdc: true, + 0xdd: true, + 0xde: true, + 0xdf: true, + 0xe0: true, + 0xe1: true, + 0xe2: true, + 0xe3: true, + 0xe4: true, + 0xe5: true, + 0xe6: true, + 0xe7: true, + 0xe8: true, + 0xe9: true, + 0xea: true, + 0xeb: true, + 0xec: true, + 0xed: true, + 0xee: true, + 0xef: true, + 0xf0: true, + 0xf1: true, + 0xf2: true, + 0xf3: true, + 0xf4: true, + 0xf5: true, + 0xf6: true, + 0xf7: true, + 0xf8: true, + 0xf9: true, + 0xfa: true, + 0xfb: true, + 0xfc: true, + 0xfd: true, + 0xfe: true, + 0xff: true, +} + +var needEscapeHTML = [256]bool{ + '"': true, + '&': true, + '<': true, + '>': true, + '\\': true, + 0x00: true, + 0x01: true, + 0x02: true, + 0x03: true, + 0x04: true, + 0x05: true, + 0x06: true, + 0x07: true, + 0x08: true, + 0x09: true, + 0x0a: true, + 0x0b: true, + 0x0c: true, + 0x0d: true, + 0x0e: true, + 0x0f: true, + 0x10: true, + 0x11: true, + 0x12: true, + 0x13: true, + 0x14: true, + 0x15: true, + 0x16: true, + 0x17: true, + 0x18: true, + 0x19: true, + 0x1a: true, + 0x1b: true, + 0x1c: true, + 0x1d: true, + 0x1e: true, + 0x1f: true, + /* 0x20 - 0xff */ +} + +var needEscape = [256]bool{ + '"': true, + '\\': true, + 0x00: true, + 0x01: true, + 0x02: true, + 0x03: true, + 0x04: true, + 0x05: true, + 0x06: true, + 0x07: true, + 0x08: true, + 0x09: true, + 0x0a: true, + 0x0b: true, + 0x0c: true, + 0x0d: true, + 0x0e: true, + 0x0f: true, + 0x10: true, + 0x11: true, + 0x12: true, + 0x13: true, + 0x14: true, + 0x15: true, + 0x16: true, + 0x17: true, + 0x18: true, + 0x19: true, + 0x1a: true, + 0x1b: true, + 0x1c: true, + 0x1d: true, + 0x1e: true, + 0x1f: true, + /* 0x20 - 0xff */ +} diff --git a/vendor/github.com/goccy/go-json/internal/encoder/vm/debug_vm.go b/vendor/github.com/goccy/go-json/internal/encoder/vm/debug_vm.go new file mode 100644 index 000000000..82b6dd47f --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/encoder/vm/debug_vm.go @@ -0,0 +1,41 @@ +package vm + +import ( + "fmt" + "io" + + "github.com/goccy/go-json/internal/encoder" +) + +func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) { + defer func() { + var code *encoder.Opcode + if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 { + code = codeSet.EscapeKeyCode + } else { + code = codeSet.NoescapeKeyCode + } + if wc := ctx.Option.DebugDOTOut; wc != nil { + _, _ = io.WriteString(wc, code.DumpDOT()) + wc.Close() + ctx.Option.DebugDOTOut = nil + } + + if err := recover(); err != nil { + w := ctx.Option.DebugOut + fmt.Fprintln(w, "=============[DEBUG]===============") + fmt.Fprintln(w, "* [TYPE]") + fmt.Fprintln(w, codeSet.Type) + fmt.Fprintf(w, "\n") + fmt.Fprintln(w, "* [ALL OPCODE]") + fmt.Fprintln(w, code.Dump()) + fmt.Fprintf(w, "\n") + fmt.Fprintln(w, "* [CONTEXT]") + fmt.Fprintf(w, "%+v\n", ctx) + fmt.Fprintln(w, "===================================") + panic(err) + } + }() + + return Run(ctx, b, codeSet) +} diff --git a/vendor/github.com/goccy/go-json/internal/encoder/vm/hack.go b/vendor/github.com/goccy/go-json/internal/encoder/vm/hack.go new file mode 100644 index 000000000..65252b4a5 --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/encoder/vm/hack.go @@ -0,0 +1,9 @@ +package vm + +import ( + // HACK: compile order + // `vm`, `vm_indent`, `vm_color`, `vm_color_indent` packages uses a lot of memory to compile, + // so forcibly make dependencies and avoid compiling in concurrent. + // dependency order: vm => vm_indent => vm_color => vm_color_indent + _ "github.com/goccy/go-json/internal/encoder/vm_indent" +) diff --git a/vendor/github.com/goccy/go-json/internal/encoder/vm/util.go b/vendor/github.com/goccy/go-json/internal/encoder/vm/util.go new file mode 100644 index 000000000..86291d7bb --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/encoder/vm/util.go @@ -0,0 +1,207 @@ +package vm + +import ( + "encoding/json" + "fmt" + "unsafe" + + "github.com/goccy/go-json/internal/encoder" + "github.com/goccy/go-json/internal/runtime" +) + +const uintptrSize = 4 << (^uintptr(0) >> 63) + +var ( + appendInt = encoder.AppendInt + appendUint = encoder.AppendUint + appendFloat32 = encoder.AppendFloat32 + appendFloat64 = encoder.AppendFloat64 + appendString = encoder.AppendString + appendByteSlice = encoder.AppendByteSlice + appendNumber = encoder.AppendNumber + errUnsupportedValue = encoder.ErrUnsupportedValue + errUnsupportedFloat = encoder.ErrUnsupportedFloat + mapiterinit = encoder.MapIterInit + mapiterkey = encoder.MapIterKey + mapitervalue = encoder.MapIterValue + mapiternext = encoder.MapIterNext + maplen = encoder.MapLen +) + +type emptyInterface struct { + typ *runtime.Type + ptr unsafe.Pointer +} + +type nonEmptyInterface struct { + itab *struct { + ityp *runtime.Type // static interface type + typ *runtime.Type // dynamic concrete type + // unused fields... + } + ptr unsafe.Pointer +} + +func errUnimplementedOp(op encoder.OpType) error { + return fmt.Errorf("encoder: opcode %s has not been implemented", op) +} + +func load(base uintptr, idx uint32) uintptr { + addr := base + uintptr(idx) + return **(**uintptr)(unsafe.Pointer(&addr)) +} + +func store(base uintptr, idx uint32, p uintptr) { + addr := base + uintptr(idx) + **(**uintptr)(unsafe.Pointer(&addr)) = p +} + +func loadNPtr(base uintptr, idx uint32, ptrNum uint8) uintptr { + addr := base + uintptr(idx) + p := **(**uintptr)(unsafe.Pointer(&addr)) + for i := uint8(0); i < ptrNum; i++ { + if p == 0 { + return 0 + } + p = ptrToPtr(p) + } + return p +} + +func ptrToUint64(p uintptr, bitSize uint8) uint64 { + switch bitSize { + case 8: + return (uint64)(**(**uint8)(unsafe.Pointer(&p))) + case 16: + return (uint64)(**(**uint16)(unsafe.Pointer(&p))) + case 32: + return (uint64)(**(**uint32)(unsafe.Pointer(&p))) + case 64: + return **(**uint64)(unsafe.Pointer(&p)) + } + return 0 +} +func ptrToFloat32(p uintptr) float32 { return **(**float32)(unsafe.Pointer(&p)) } +func ptrToFloat64(p uintptr) float64 { return **(**float64)(unsafe.Pointer(&p)) } +func ptrToBool(p uintptr) bool { return **(**bool)(unsafe.Pointer(&p)) } +func ptrToBytes(p uintptr) []byte { return **(**[]byte)(unsafe.Pointer(&p)) } +func ptrToNumber(p uintptr) json.Number { return **(**json.Number)(unsafe.Pointer(&p)) } +func ptrToString(p uintptr) string { return **(**string)(unsafe.Pointer(&p)) } +func ptrToSlice(p uintptr) *runtime.SliceHeader { return *(**runtime.SliceHeader)(unsafe.Pointer(&p)) } +func ptrToPtr(p uintptr) uintptr { + return uintptr(**(**unsafe.Pointer)(unsafe.Pointer(&p))) +} +func ptrToNPtr(p uintptr, ptrNum uint8) uintptr { + for i := uint8(0); i < ptrNum; i++ { + if p == 0 { + return 0 + } + p = ptrToPtr(p) + } + return p +} + +func ptrToUnsafePtr(p uintptr) unsafe.Pointer { + return *(*unsafe.Pointer)(unsafe.Pointer(&p)) +} +func ptrToInterface(code *encoder.Opcode, p uintptr) interface{} { + return *(*interface{})(unsafe.Pointer(&emptyInterface{ + typ: code.Type, + ptr: *(*unsafe.Pointer)(unsafe.Pointer(&p)), + })) +} + +func appendBool(_ *encoder.RuntimeContext, b []byte, v bool) []byte { + if v { + return append(b, "true"...) + } + return append(b, "false"...) +} + +func appendNull(_ *encoder.RuntimeContext, b []byte) []byte { + return append(b, "null"...) +} + +func appendComma(_ *encoder.RuntimeContext, b []byte) []byte { + return append(b, ',') +} + +func appendNullComma(_ *encoder.RuntimeContext, b []byte) []byte { + return append(b, "null,"...) +} + +func appendColon(_ *encoder.RuntimeContext, b []byte) []byte { + last := len(b) - 1 + b[last] = ':' + return b +} + +func appendMapKeyValue(_ *encoder.RuntimeContext, _ *encoder.Opcode, b, key, value []byte) []byte { + b = append(b, key...) + b[len(b)-1] = ':' + return append(b, value...) +} + +func appendMapEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte { + b[len(b)-1] = '}' + b = append(b, ',') + return b +} + +func appendMarshalJSON(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte, v interface{}) ([]byte, error) { + return encoder.AppendMarshalJSON(ctx, code, b, v) +} + +func appendMarshalText(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte, v interface{}) ([]byte, error) { + return encoder.AppendMarshalText(ctx, code, b, v) +} + +func appendArrayHead(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte { + return append(b, '[') +} + +func appendArrayEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte { + last := len(b) - 1 + b[last] = ']' + return append(b, ',') +} + +func appendEmptyArray(_ *encoder.RuntimeContext, b []byte) []byte { + return append(b, '[', ']', ',') +} + +func appendEmptyObject(_ *encoder.RuntimeContext, b []byte) []byte { + return append(b, '{', '}', ',') +} + +func appendObjectEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte { + last := len(b) - 1 + b[last] = '}' + return append(b, ',') +} + +func appendStructHead(_ *encoder.RuntimeContext, b []byte) []byte { + return append(b, '{') +} + +func appendStructKey(_ *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { + return append(b, code.Key...) +} + +func appendStructEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte { + return append(b, '}', ',') +} + +func appendStructEndSkipLast(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { + last := len(b) - 1 + if b[last] == ',' { + b[last] = '}' + return appendComma(ctx, b) + } + return appendStructEnd(ctx, code, b) +} + +func restoreIndent(_ *encoder.RuntimeContext, _ *encoder.Opcode, _ uintptr) {} +func storeIndent(_ uintptr, _ *encoder.Opcode, _ uintptr) {} +func appendMapKeyIndent(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte { return b } +func appendArrayElemIndent(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte { return b } diff --git a/vendor/github.com/goccy/go-json/internal/encoder/vm/vm.go b/vendor/github.com/goccy/go-json/internal/encoder/vm/vm.go new file mode 100644 index 000000000..645d20f9f --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/encoder/vm/vm.go @@ -0,0 +1,4859 @@ +// Code generated by internal/cmd/generator. DO NOT EDIT! +package vm + +import ( + "math" + "reflect" + "sort" + "unsafe" + + "github.com/goccy/go-json/internal/encoder" + "github.com/goccy/go-json/internal/runtime" +) + +func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) { + recursiveLevel := 0 + ptrOffset := uintptr(0) + ctxptr := ctx.Ptr() + var code *encoder.Opcode + if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 { + code = codeSet.EscapeKeyCode + } else { + code = codeSet.NoescapeKeyCode + } + + for { + switch code.Op { + default: + return nil, errUnimplementedOp(code.Op) + case encoder.OpPtr: + p := load(ctxptr, code.Idx) + code = code.Next + store(ctxptr, code.Idx, ptrToPtr(p)) + case encoder.OpIntPtr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpInt: + b = appendInt(ctx, b, load(ctxptr, code.Idx), code) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpUintPtr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpUint: + b = appendUint(ctx, b, load(ctxptr, code.Idx), code) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpIntString: + b = append(b, '"') + b = appendInt(ctx, b, load(ctxptr, code.Idx), code) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpUintString: + b = append(b, '"') + b = appendUint(ctx, b, load(ctxptr, code.Idx), code) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpFloat32Ptr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + b = appendComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpFloat32: + b = appendFloat32(ctx, b, ptrToFloat32(load(ctxptr, code.Idx))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpFloat64Ptr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpFloat64: + v := ptrToFloat64(load(ctxptr, code.Idx)) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStringPtr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpString: + b = appendString(ctx, b, ptrToString(load(ctxptr, code.Idx))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpBoolPtr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpBool: + b = appendBool(ctx, b, ptrToBool(load(ctxptr, code.Idx))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpBytesPtr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpBytes: + b = appendByteSlice(ctx, b, ptrToBytes(load(ctxptr, code.Idx))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpNumberPtr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpNumber: + bb, err := appendNumber(ctx, b, ptrToNumber(load(ctxptr, code.Idx))) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + code = code.Next + case encoder.OpInterfacePtr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpInterface: + p := load(ctxptr, code.Idx) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + if recursiveLevel > encoder.StartDetectingCyclesAfter { + for _, seen := range ctx.SeenPtr { + if p == seen { + return nil, errUnsupportedValue(code, p) + } + } + } + ctx.SeenPtr = append(ctx.SeenPtr, p) + var ( + typ *runtime.Type + ifacePtr unsafe.Pointer + ) + up := ptrToUnsafePtr(p) + if code.Flags&encoder.NonEmptyInterfaceFlags != 0 { + iface := (*nonEmptyInterface)(up) + ifacePtr = iface.ptr + if iface.itab != nil { + typ = iface.itab.typ + } + } else { + iface := (*emptyInterface)(up) + ifacePtr = iface.ptr + typ = iface.typ + } + if ifacePtr == nil { + isDirectedNil := typ != nil && typ.Kind() == reflect.Struct && !runtime.IfaceIndir(typ) + if !isDirectedNil { + b = appendNullComma(ctx, b) + code = code.Next + break + } + } + ctx.KeepRefs = append(ctx.KeepRefs, up) + ifaceCodeSet, err := encoder.CompileToGetCodeSet(ctx, uintptr(unsafe.Pointer(typ))) + if err != nil { + return nil, err + } + + totalLength := uintptr(code.Length) + 3 + nextTotalLength := uintptr(ifaceCodeSet.CodeLength) + 3 + + var c *encoder.Opcode + if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 { + c = ifaceCodeSet.InterfaceEscapeKeyCode + } else { + c = ifaceCodeSet.InterfaceNoescapeKeyCode + } + curlen := uintptr(len(ctx.Ptrs)) + offsetNum := ptrOffset / uintptrSize + oldOffset := ptrOffset + ptrOffset += totalLength * uintptrSize + oldBaseIndent := ctx.BaseIndent + ctx.BaseIndent += code.Indent + + newLen := offsetNum + totalLength + nextTotalLength + if curlen < newLen { + ctx.Ptrs = append(ctx.Ptrs, make([]uintptr, newLen-curlen)...) + } + ctxptr = ctx.Ptr() + ptrOffset // assign new ctxptr + + end := ifaceCodeSet.EndCode + store(ctxptr, c.Idx, uintptr(ifacePtr)) + store(ctxptr, end.Idx, oldOffset) + store(ctxptr, end.ElemIdx, uintptr(unsafe.Pointer(code.Next))) + storeIndent(ctxptr, end, uintptr(oldBaseIndent)) + code = c + recursiveLevel++ + case encoder.OpInterfaceEnd: + recursiveLevel-- + + // restore ctxptr + offset := load(ctxptr, code.Idx) + restoreIndent(ctx, code, ctxptr) + ctx.SeenPtr = ctx.SeenPtr[:len(ctx.SeenPtr)-1] + + codePtr := load(ctxptr, code.ElemIdx) + code = (*encoder.Opcode)(ptrToUnsafePtr(codePtr)) + ctxptr = ctx.Ptr() + offset + ptrOffset = offset + case encoder.OpMarshalJSONPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, ptrToPtr(p)) + fallthrough + case encoder.OpMarshalJSON: + p := load(ctxptr, code.Idx) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + if (code.Flags&encoder.IsNilableTypeFlags) != 0 && (code.Flags&encoder.IndirectFlags) != 0 { + p = ptrToPtr(p) + } + bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + code = code.Next + case encoder.OpMarshalTextPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, ptrToPtr(p)) + fallthrough + case encoder.OpMarshalText: + p := load(ctxptr, code.Idx) + if p == 0 { + b = append(b, `""`...) + b = appendComma(ctx, b) + code = code.Next + break + } + if (code.Flags&encoder.IsNilableTypeFlags) != 0 && (code.Flags&encoder.IndirectFlags) != 0 { + p = ptrToPtr(p) + } + bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + code = code.Next + case encoder.OpSlicePtr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.End.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpSlice: + p := load(ctxptr, code.Idx) + slice := ptrToSlice(p) + if p == 0 || slice.Data == nil { + b = appendNullComma(ctx, b) + code = code.End.Next + break + } + store(ctxptr, code.ElemIdx, 0) + store(ctxptr, code.Length, uintptr(slice.Len)) + store(ctxptr, code.Idx, uintptr(slice.Data)) + if slice.Len > 0 { + b = appendArrayHead(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, uintptr(slice.Data)) + } else { + b = appendEmptyArray(ctx, b) + code = code.End.Next + } + case encoder.OpSliceElem: + idx := load(ctxptr, code.ElemIdx) + length := load(ctxptr, code.Length) + idx++ + if idx < length { + b = appendArrayElemIndent(ctx, code, b) + store(ctxptr, code.ElemIdx, idx) + data := load(ctxptr, code.Idx) + size := uintptr(code.Size) + code = code.Next + store(ctxptr, code.Idx, data+idx*size) + } else { + b = appendArrayEnd(ctx, code, b) + code = code.End.Next + } + case encoder.OpArrayPtr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.End.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpArray: + p := load(ctxptr, code.Idx) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.End.Next + break + } + if code.Length > 0 { + b = appendArrayHead(ctx, code, b) + store(ctxptr, code.ElemIdx, 0) + code = code.Next + store(ctxptr, code.Idx, p) + } else { + b = appendEmptyArray(ctx, b) + code = code.End.Next + } + case encoder.OpArrayElem: + idx := load(ctxptr, code.ElemIdx) + idx++ + if idx < uintptr(code.Length) { + b = appendArrayElemIndent(ctx, code, b) + store(ctxptr, code.ElemIdx, idx) + p := load(ctxptr, code.Idx) + size := uintptr(code.Size) + code = code.Next + store(ctxptr, code.Idx, p+idx*size) + } else { + b = appendArrayEnd(ctx, code, b) + code = code.End.Next + } + case encoder.OpMapPtr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.End.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpMap: + p := load(ctxptr, code.Idx) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.End.Next + break + } + uptr := ptrToUnsafePtr(p) + mlen := maplen(uptr) + if mlen <= 0 { + b = appendEmptyObject(ctx, b) + code = code.End.Next + break + } + b = appendStructHead(ctx, b) + unorderedMap := (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 + mapCtx := encoder.NewMapContext(mlen, unorderedMap) + mapiterinit(code.Type, uptr, &mapCtx.Iter) + store(ctxptr, code.Idx, uintptr(unsafe.Pointer(mapCtx))) + ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(mapCtx)) + if unorderedMap { + b = appendMapKeyIndent(ctx, code.Next, b) + } else { + mapCtx.Start = len(b) + mapCtx.First = len(b) + } + key := mapiterkey(&mapCtx.Iter) + store(ctxptr, code.Next.Idx, uintptr(key)) + code = code.Next + case encoder.OpMapKey: + mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.Idx))) + idx := mapCtx.Idx + idx++ + if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 { + if idx < mapCtx.Len { + b = appendMapKeyIndent(ctx, code, b) + mapCtx.Idx = int(idx) + key := mapiterkey(&mapCtx.Iter) + store(ctxptr, code.Next.Idx, uintptr(key)) + code = code.Next + } else { + b = appendObjectEnd(ctx, code, b) + encoder.ReleaseMapContext(mapCtx) + code = code.End.Next + } + } else { + mapCtx.Slice.Items[mapCtx.Idx].Value = b[mapCtx.Start:len(b)] + if idx < mapCtx.Len { + mapCtx.Idx = int(idx) + mapCtx.Start = len(b) + key := mapiterkey(&mapCtx.Iter) + store(ctxptr, code.Next.Idx, uintptr(key)) + code = code.Next + } else { + code = code.End + } + } + case encoder.OpMapValue: + mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.Idx))) + if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 { + b = appendColon(ctx, b) + } else { + mapCtx.Slice.Items[mapCtx.Idx].Key = b[mapCtx.Start:len(b)] + mapCtx.Start = len(b) + } + value := mapitervalue(&mapCtx.Iter) + store(ctxptr, code.Next.Idx, uintptr(value)) + mapiternext(&mapCtx.Iter) + code = code.Next + case encoder.OpMapEnd: + // this operation only used by sorted map. + mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.Idx))) + sort.Sort(mapCtx.Slice) + buf := mapCtx.Buf + for _, item := range mapCtx.Slice.Items { + buf = appendMapKeyValue(ctx, code, buf, item.Key, item.Value) + } + buf = appendMapEnd(ctx, code, buf) + b = b[:mapCtx.First] + b = append(b, buf...) + mapCtx.Buf = buf + encoder.ReleaseMapContext(mapCtx) + code = code.Next + case encoder.OpRecursivePtr: + p := load(ctxptr, code.Idx) + if p == 0 { + code = code.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpRecursive: + ptr := load(ctxptr, code.Idx) + if ptr != 0 { + if recursiveLevel > encoder.StartDetectingCyclesAfter { + for _, seen := range ctx.SeenPtr { + if ptr == seen { + return nil, errUnsupportedValue(code, ptr) + } + } + } + } + ctx.SeenPtr = append(ctx.SeenPtr, ptr) + c := code.Jmp.Code + curlen := uintptr(len(ctx.Ptrs)) + offsetNum := ptrOffset / uintptrSize + oldOffset := ptrOffset + ptrOffset += code.Jmp.CurLen * uintptrSize + oldBaseIndent := ctx.BaseIndent + indentDiffFromTop := c.Indent - 1 + ctx.BaseIndent += code.Indent - indentDiffFromTop + + newLen := offsetNum + code.Jmp.CurLen + code.Jmp.NextLen + if curlen < newLen { + ctx.Ptrs = append(ctx.Ptrs, make([]uintptr, newLen-curlen)...) + } + ctxptr = ctx.Ptr() + ptrOffset // assign new ctxptr + + store(ctxptr, c.Idx, ptr) + store(ctxptr, c.End.Next.Idx, oldOffset) + store(ctxptr, c.End.Next.ElemIdx, uintptr(unsafe.Pointer(code.Next))) + storeIndent(ctxptr, c.End.Next, uintptr(oldBaseIndent)) + code = c + recursiveLevel++ + case encoder.OpRecursiveEnd: + recursiveLevel-- + + // restore ctxptr + restoreIndent(ctx, code, ctxptr) + offset := load(ctxptr, code.Idx) + ctx.SeenPtr = ctx.SeenPtr[:len(ctx.SeenPtr)-1] + + codePtr := load(ctxptr, code.ElemIdx) + code = (*encoder.Opcode)(ptrToUnsafePtr(codePtr)) + ctxptr = ctx.Ptr() + offset + ptrOffset = offset + case encoder.OpStructPtrHead: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHead: + p := load(ctxptr, code.Idx) + if p == 0 && ((code.Flags&encoder.IndirectFlags) != 0 || code.Next.Op == encoder.OpStructEnd) { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if len(code.Key) > 0 { + if (code.Flags&encoder.IsTaggedKeyFlags) != 0 || code.Flags&encoder.AnonymousKeyFlags == 0 { + b = appendStructKey(ctx, code, b) + } + } + p += uintptr(code.Offset) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructPtrHeadOmitEmpty: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmpty: + p := load(ctxptr, code.Idx) + if p == 0 && ((code.Flags&encoder.IndirectFlags) != 0 || code.Next.Op == encoder.OpStructEnd) { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + p += uintptr(code.Offset) + if p == 0 || (ptrToPtr(p) == 0 && (code.Flags&encoder.IsNextOpPtrTypeFlags) != 0) { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructPtrHeadInt: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadInt: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyInt: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyInt: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadIntString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadIntString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyIntString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyIntString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + p += uintptr(code.Offset) + u64 := ptrToUint64(p, code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendInt(ctx, b, p, code) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadIntPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadIntPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendInt(ctx, b, p, code) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyIntPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyIntPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendInt(ctx, b, p, code) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadIntPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadIntPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendInt(ctx, b, p, code) + b = append(b, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyIntPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyIntPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendInt(ctx, b, p, code) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadUint: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadUint: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyUint: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyUint: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadUintString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadUintString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyUintString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyUintString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadUintPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadUintPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendUint(ctx, b, p, code) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyUintPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyUintPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendUint(ctx, b, p, code) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadUintPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadUintPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendUint(ctx, b, p, code) + b = append(b, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyUintPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyUintPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendUint(ctx, b, p, code) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadFloat32: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadFloat32: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyFloat32: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyFloat32: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToFloat32(p + uintptr(code.Offset)) + if v == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + b = appendFloat32(ctx, b, v) + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadFloat32String: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadFloat32String: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyFloat32String: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyFloat32String: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToFloat32(p + uintptr(code.Offset)) + if v == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat32(ctx, b, v) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadFloat32Ptr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadFloat32Ptr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendFloat32(ctx, b, ptrToFloat32(p)) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyFloat32Ptr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyFloat32Ptr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendFloat32(ctx, b, ptrToFloat32(p)) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadFloat32PtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadFloat32PtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendFloat32(ctx, b, ptrToFloat32(p)) + b = append(b, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyFloat32PtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyFloat32PtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat32(ctx, b, ptrToFloat32(p)) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadFloat64: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadFloat64: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + v := ptrToFloat64(p + uintptr(code.Offset)) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = appendFloat64(ctx, b, v) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyFloat64: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyFloat64: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToFloat64(p + uintptr(code.Offset)) + if v == 0 { + code = code.NextField + } else { + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendStructKey(ctx, code, b) + b = appendFloat64(ctx, b, v) + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadFloat64String: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadFloat64String: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToFloat64(p + uintptr(code.Offset)) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat64(ctx, b, v) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyFloat64String: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyFloat64String: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToFloat64(p + uintptr(code.Offset)) + if v == 0 { + code = code.NextField + } else { + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat64(ctx, b, v) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadFloat64Ptr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadFloat64Ptr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyFloat64Ptr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyFloat64Ptr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadFloat64PtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadFloat64PtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = append(b, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyFloat64PtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyFloat64PtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNull(ctx, b) + b = appendComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, ptrToString(p+uintptr(code.Offset))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToString(p + uintptr(code.Offset)) + if v == "" { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, v) + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadStringString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadStringString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p+uintptr(code.Offset))))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyStringString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyStringString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToString(p + uintptr(code.Offset)) + if v == "" { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, string(appendString(ctx, []byte{}, v))) + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadStringPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadStringPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendString(ctx, b, ptrToString(p)) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyStringPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyStringPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, ptrToString(p)) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadStringPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadStringPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyStringPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyStringPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadBool: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadBool: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyBool: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyBool: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToBool(p + uintptr(code.Offset)) + if v { + b = appendStructKey(ctx, code, b) + b = appendBool(ctx, b, v) + b = appendComma(ctx, b) + code = code.Next + } else { + code = code.NextField + } + case encoder.OpStructPtrHeadBoolString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadBoolString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyBoolString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyBoolString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToBool(p + uintptr(code.Offset)) + if v { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendBool(ctx, b, v) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + } else { + code = code.NextField + } + case encoder.OpStructPtrHeadBoolPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadBoolPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendBool(ctx, b, ptrToBool(p)) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyBoolPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyBoolPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendBool(ctx, b, ptrToBool(p)) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadBoolPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadBoolPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendBool(ctx, b, ptrToBool(p)) + b = append(b, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyBoolPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyBoolPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendBool(ctx, b, ptrToBool(p)) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadBytes: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadBytes: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = appendByteSlice(ctx, b, ptrToBytes(p+uintptr(code.Offset))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyBytes: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyBytes: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToBytes(p + uintptr(code.Offset)) + if len(v) == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + b = appendByteSlice(ctx, b, v) + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadBytesPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadBytesPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendByteSlice(ctx, b, ptrToBytes(p)) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyBytesPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyBytesPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendByteSlice(ctx, b, ptrToBytes(p)) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadNumber: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadNumber: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyNumber: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyNumber: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToNumber(p + uintptr(code.Offset)) + if v == "" { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + bb, err := appendNumber(ctx, b, v) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + code = code.Next + } + case encoder.OpStructPtrHeadNumberString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadNumberString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) + if err != nil { + return nil, err + } + b = append(bb, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyNumberString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyNumberString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToNumber(p + uintptr(code.Offset)) + if v == "" { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + bb, err := appendNumber(ctx, b, v) + if err != nil { + return nil, err + } + b = append(bb, '"') + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadNumberPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadNumberPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyNumberPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyNumberPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + } + code = code.Next + case encoder.OpStructPtrHeadNumberPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadNumberPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = append(bb, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyNumberPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyNumberPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = append(bb, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadArray, encoder.OpStructPtrHeadSlice: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadArray, encoder.OpStructHeadSlice: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + p += uintptr(code.Offset) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructPtrHeadOmitEmptyArray: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyArray: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + p += uintptr(code.Offset) + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructPtrHeadOmitEmptySlice: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptySlice: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + p += uintptr(code.Offset) + slice := ptrToSlice(p) + if slice.Len == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructPtrHeadArrayPtr, encoder.OpStructPtrHeadSlicePtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadArrayPtr, encoder.OpStructHeadSlicePtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNullComma(ctx, b) + code = code.NextField + } else { + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructPtrHeadOmitEmptyArrayPtr, encoder.OpStructPtrHeadOmitEmptySlicePtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyArrayPtr, encoder.OpStructHeadOmitEmptySlicePtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructPtrHeadMap: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadMap: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if p != 0 && (code.Flags&encoder.IndirectFlags) != 0 { + p = ptrToPtr(p + uintptr(code.Offset)) + } + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructPtrHeadOmitEmptyMap: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyMap: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if p != 0 && (code.Flags&encoder.IndirectFlags) != 0 { + p = ptrToPtr(p + uintptr(code.Offset)) + } + if maplen(ptrToUnsafePtr(p)) == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructPtrHeadMapPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadMapPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.NextField + break + } + p = ptrToPtr(p + uintptr(code.Offset)) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.NextField + } else { + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p, code.PtrNum) + } + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructPtrHeadOmitEmptyMapPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyMapPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if p == 0 { + code = code.NextField + break + } + p = ptrToPtr(p + uintptr(code.Offset)) + if p == 0 { + code = code.NextField + } else { + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p, code.PtrNum) + } + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructPtrHeadMarshalJSON: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if (code.Flags & encoder.IndirectFlags) != 0 { + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadMarshalJSON: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + p += uintptr(code.Offset) + if (code.Flags & encoder.IsNilableTypeFlags) != 0 { + if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadMarshalJSON { + p = ptrToPtr(p) + } + } + if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyMarshalJSON: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if (code.Flags & encoder.IndirectFlags) != 0 { + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyMarshalJSON: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + p += uintptr(code.Offset) + if (code.Flags & encoder.IsNilableTypeFlags) != 0 { + if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadOmitEmptyMarshalJSON { + p = ptrToPtr(p) + } + } + iface := ptrToInterface(code, p) + if (code.Flags&encoder.NilCheckFlags) != 0 && encoder.IsNilForMarshaler(iface) { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + bb, err := appendMarshalJSON(ctx, code, b, iface) + if err != nil { + return nil, err + } + b = bb + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadMarshalJSONPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadMarshalJSONPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyMarshalJSONPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyMarshalJSONPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if p == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadMarshalText: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if (code.Flags & encoder.IndirectFlags) != 0 { + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadMarshalText: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + p += uintptr(code.Offset) + if (code.Flags & encoder.IsNilableTypeFlags) != 0 { + if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadMarshalText { + p = ptrToPtr(p) + } + } + if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyMarshalText: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if (code.Flags & encoder.IndirectFlags) != 0 { + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyMarshalText: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + p += uintptr(code.Offset) + if (code.Flags & encoder.IsNilableTypeFlags) != 0 { + if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadOmitEmptyMarshalText { + p = ptrToPtr(p) + } + } + if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadMarshalTextPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadMarshalTextPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyMarshalTextPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyMarshalTextPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if p == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructField: + if code.Flags&encoder.IsTaggedKeyFlags != 0 || code.Flags&encoder.AnonymousKeyFlags == 0 { + b = appendStructKey(ctx, code, b) + } + p := load(ctxptr, code.Idx) + uintptr(code.Offset) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructFieldOmitEmpty: + p := load(ctxptr, code.Idx) + p += uintptr(code.Offset) + if ptrToPtr(p) == 0 && (code.Flags&encoder.IsNextOpPtrTypeFlags) != 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructFieldInt: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyInt: + p := load(ctxptr, code.Idx) + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldIntString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyIntString: + p := load(ctxptr, code.Idx) + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldIntPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendInt(ctx, b, p, code) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyIntPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendInt(ctx, b, p, code) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldIntPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendInt(ctx, b, p, code) + b = append(b, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyIntPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendInt(ctx, b, p, code) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldUint: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyUint: + p := load(ctxptr, code.Idx) + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldUintString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyUintString: + p := load(ctxptr, code.Idx) + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldUintPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendUint(ctx, b, p, code) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyUintPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendUint(ctx, b, p, code) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldUintPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendUint(ctx, b, p, code) + b = append(b, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyUintPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendUint(ctx, b, p, code) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldFloat32: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyFloat32: + p := load(ctxptr, code.Idx) + v := ptrToFloat32(p + uintptr(code.Offset)) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = appendFloat32(ctx, b, v) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldFloat32String: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyFloat32String: + p := load(ctxptr, code.Idx) + v := ptrToFloat32(p + uintptr(code.Offset)) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat32(ctx, b, v) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldFloat32Ptr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendFloat32(ctx, b, ptrToFloat32(p)) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyFloat32Ptr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendFloat32(ctx, b, ptrToFloat32(p)) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldFloat32PtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendFloat32(ctx, b, ptrToFloat32(p)) + b = append(b, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyFloat32PtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat32(ctx, b, ptrToFloat32(p)) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldFloat64: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + v := ptrToFloat64(p + uintptr(code.Offset)) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyFloat64: + p := load(ctxptr, code.Idx) + v := ptrToFloat64(p + uintptr(code.Offset)) + if v != 0 { + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendStructKey(ctx, code, b) + b = appendFloat64(ctx, b, v) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldFloat64String: + p := load(ctxptr, code.Idx) + v := ptrToFloat64(p + uintptr(code.Offset)) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat64(ctx, b, v) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyFloat64String: + p := load(ctxptr, code.Idx) + v := ptrToFloat64(p + uintptr(code.Offset)) + if v != 0 { + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat64(ctx, b, v) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldFloat64Ptr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyFloat64Ptr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldFloat64PtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = append(b, '"') + b = appendFloat64(ctx, b, v) + b = append(b, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyFloat64PtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, ptrToString(p+uintptr(code.Offset))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyString: + p := load(ctxptr, code.Idx) + v := ptrToString(p + uintptr(code.Offset)) + if v != "" { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, v) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldStringString: + p := load(ctxptr, code.Idx) + s := ptrToString(p + uintptr(code.Offset)) + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, string(appendString(ctx, []byte{}, s))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyStringString: + p := load(ctxptr, code.Idx) + v := ptrToString(p + uintptr(code.Offset)) + if v != "" { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, string(appendString(ctx, []byte{}, v))) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldStringPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendString(ctx, b, ptrToString(p)) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyStringPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, ptrToString(p)) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldStringPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyStringPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldBool: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyBool: + p := load(ctxptr, code.Idx) + v := ptrToBool(p + uintptr(code.Offset)) + if v { + b = appendStructKey(ctx, code, b) + b = appendBool(ctx, b, v) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldBoolString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyBoolString: + p := load(ctxptr, code.Idx) + v := ptrToBool(p + uintptr(code.Offset)) + if v { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendBool(ctx, b, v) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldBoolPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendBool(ctx, b, ptrToBool(p)) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyBoolPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendBool(ctx, b, ptrToBool(p)) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldBoolPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendBool(ctx, b, ptrToBool(p)) + b = append(b, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyBoolPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendBool(ctx, b, ptrToBool(p)) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldBytes: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendByteSlice(ctx, b, ptrToBytes(p+uintptr(code.Offset))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyBytes: + p := load(ctxptr, code.Idx) + v := ptrToBytes(p + uintptr(code.Offset)) + if len(v) > 0 { + b = appendStructKey(ctx, code, b) + b = appendByteSlice(ctx, b, v) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldBytesPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendByteSlice(ctx, b, ptrToBytes(p)) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyBytesPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendByteSlice(ctx, b, ptrToBytes(p)) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldNumber: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + code = code.Next + case encoder.OpStructFieldOmitEmptyNumber: + p := load(ctxptr, code.Idx) + v := ptrToNumber(p + uintptr(code.Offset)) + if v != "" { + b = appendStructKey(ctx, code, b) + bb, err := appendNumber(ctx, b, v) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + } + code = code.Next + case encoder.OpStructFieldNumberString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = append(b, '"') + bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) + if err != nil { + return nil, err + } + b = append(bb, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyNumberString: + p := load(ctxptr, code.Idx) + v := ptrToNumber(p + uintptr(code.Offset)) + if v != "" { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + bb, err := appendNumber(ctx, b, v) + if err != nil { + return nil, err + } + b = append(bb, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldNumberPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyNumberPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + } + code = code.Next + case encoder.OpStructFieldNumberPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = append(bb, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyNumberPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = append(bb, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldMarshalJSON: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + p += uintptr(code.Offset) + if (code.Flags & encoder.IsNilableTypeFlags) != 0 { + p = ptrToPtr(p) + } + if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyMarshalJSON: + p := load(ctxptr, code.Idx) + p += uintptr(code.Offset) + if (code.Flags & encoder.IsNilableTypeFlags) != 0 { + p = ptrToPtr(p) + } + if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { + code = code.NextField + break + } + iface := ptrToInterface(code, p) + if (code.Flags&encoder.NilCheckFlags) != 0 && encoder.IsNilForMarshaler(iface) { + code = code.NextField + break + } + b = appendStructKey(ctx, code, b) + bb, err := appendMarshalJSON(ctx, code, b, iface) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + code = code.Next + case encoder.OpStructFieldMarshalJSONPtr: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyMarshalJSONPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + } + code = code.Next + case encoder.OpStructFieldMarshalText: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + p += uintptr(code.Offset) + if (code.Flags & encoder.IsNilableTypeFlags) != 0 { + p = ptrToPtr(p) + } + if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyMarshalText: + p := load(ctxptr, code.Idx) + p += uintptr(code.Offset) + if (code.Flags & encoder.IsNilableTypeFlags) != 0 { + p = ptrToPtr(p) + } + if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { + code = code.NextField + break + } + b = appendStructKey(ctx, code, b) + bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + code = code.Next + case encoder.OpStructFieldMarshalTextPtr: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyMarshalTextPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + } + code = code.Next + case encoder.OpStructFieldArray: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p += uintptr(code.Offset) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructFieldOmitEmptyArray: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p += uintptr(code.Offset) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructFieldArrayPtr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructFieldOmitEmptyArrayPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } else { + code = code.NextField + } + case encoder.OpStructFieldSlice: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p += uintptr(code.Offset) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructFieldOmitEmptySlice: + p := load(ctxptr, code.Idx) + p += uintptr(code.Offset) + slice := ptrToSlice(p) + if slice.Len == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructFieldSlicePtr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructFieldOmitEmptySlicePtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } else { + code = code.NextField + } + case encoder.OpStructFieldMap: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToPtr(p + uintptr(code.Offset)) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructFieldOmitEmptyMap: + p := load(ctxptr, code.Idx) + p = ptrToPtr(p + uintptr(code.Offset)) + if p == 0 || maplen(ptrToUnsafePtr(p)) == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructFieldMapPtr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToPtr(p + uintptr(code.Offset)) + if p != 0 { + p = ptrToNPtr(p, code.PtrNum) + } + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructFieldOmitEmptyMapPtr: + p := load(ctxptr, code.Idx) + p = ptrToPtr(p + uintptr(code.Offset)) + if p != 0 { + p = ptrToNPtr(p, code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } else { + code = code.NextField + } + case encoder.OpStructFieldStruct: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p += uintptr(code.Offset) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructFieldOmitEmptyStruct: + p := load(ctxptr, code.Idx) + p += uintptr(code.Offset) + if ptrToPtr(p) == 0 && (code.Flags&encoder.IsNextOpPtrTypeFlags) != 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructEnd: + b = appendStructEndSkipLast(ctx, code, b) + code = code.Next + case encoder.OpStructEndInt: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyInt: + p := load(ctxptr, code.Idx) + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndIntString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyIntString: + p := load(ctxptr, code.Idx) + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndIntPtr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendInt(ctx, b, p, code) + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyIntPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendInt(ctx, b, p, code) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndIntPtrString: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendInt(ctx, b, p, code) + b = append(b, '"') + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyIntPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendInt(ctx, b, p, code) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndUint: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyUint: + p := load(ctxptr, code.Idx) + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndUintString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyUintString: + p := load(ctxptr, code.Idx) + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndUintPtr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendUint(ctx, b, p, code) + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyUintPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendUint(ctx, b, p, code) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndUintPtrString: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendUint(ctx, b, p, code) + b = append(b, '"') + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyUintPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendUint(ctx, b, p, code) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndFloat32: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyFloat32: + p := load(ctxptr, code.Idx) + v := ptrToFloat32(p + uintptr(code.Offset)) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = appendFloat32(ctx, b, v) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndFloat32String: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyFloat32String: + p := load(ctxptr, code.Idx) + v := ptrToFloat32(p + uintptr(code.Offset)) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat32(ctx, b, v) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndFloat32Ptr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendFloat32(ctx, b, ptrToFloat32(p)) + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyFloat32Ptr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendFloat32(ctx, b, ptrToFloat32(p)) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndFloat32PtrString: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendFloat32(ctx, b, ptrToFloat32(p)) + b = append(b, '"') + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyFloat32PtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat32(ctx, b, ptrToFloat32(p)) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndFloat64: + p := load(ctxptr, code.Idx) + v := ptrToFloat64(p + uintptr(code.Offset)) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendStructKey(ctx, code, b) + b = appendFloat64(ctx, b, v) + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyFloat64: + p := load(ctxptr, code.Idx) + v := ptrToFloat64(p + uintptr(code.Offset)) + if v != 0 { + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendStructKey(ctx, code, b) + b = appendFloat64(ctx, b, v) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndFloat64String: + p := load(ctxptr, code.Idx) + v := ptrToFloat64(p + uintptr(code.Offset)) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat64(ctx, b, v) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyFloat64String: + p := load(ctxptr, code.Idx) + v := ptrToFloat64(p + uintptr(code.Offset)) + if v != 0 { + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat64(ctx, b, v) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndFloat64Ptr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + b = appendStructEnd(ctx, code, b) + code = code.Next + break + } + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyFloat64Ptr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndFloat64PtrString: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = append(b, '"') + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyFloat64PtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = append(b, '"') + b = appendFloat64(ctx, b, v) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, ptrToString(p+uintptr(code.Offset))) + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyString: + p := load(ctxptr, code.Idx) + v := ptrToString(p + uintptr(code.Offset)) + if v != "" { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, v) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndStringString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + s := ptrToString(p + uintptr(code.Offset)) + b = appendString(ctx, b, string(appendString(ctx, []byte{}, s))) + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyStringString: + p := load(ctxptr, code.Idx) + v := ptrToString(p + uintptr(code.Offset)) + if v != "" { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, string(appendString(ctx, []byte{}, v))) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndStringPtr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendString(ctx, b, ptrToString(p)) + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyStringPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, ptrToString(p)) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndStringPtrString: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyStringPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndBool: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyBool: + p := load(ctxptr, code.Idx) + v := ptrToBool(p + uintptr(code.Offset)) + if v { + b = appendStructKey(ctx, code, b) + b = appendBool(ctx, b, v) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndBoolString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyBoolString: + p := load(ctxptr, code.Idx) + v := ptrToBool(p + uintptr(code.Offset)) + if v { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendBool(ctx, b, v) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndBoolPtr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendBool(ctx, b, ptrToBool(p)) + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyBoolPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendBool(ctx, b, ptrToBool(p)) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndBoolPtrString: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendBool(ctx, b, ptrToBool(p)) + b = append(b, '"') + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyBoolPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendBool(ctx, b, ptrToBool(p)) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndBytes: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendByteSlice(ctx, b, ptrToBytes(p+uintptr(code.Offset))) + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyBytes: + p := load(ctxptr, code.Idx) + v := ptrToBytes(p + uintptr(code.Offset)) + if len(v) > 0 { + b = appendStructKey(ctx, code, b) + b = appendByteSlice(ctx, b, v) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndBytesPtr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendByteSlice(ctx, b, ptrToBytes(p)) + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyBytesPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendByteSlice(ctx, b, ptrToBytes(p)) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndNumber: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) + if err != nil { + return nil, err + } + b = appendStructEnd(ctx, code, bb) + code = code.Next + case encoder.OpStructEndOmitEmptyNumber: + p := load(ctxptr, code.Idx) + v := ptrToNumber(p + uintptr(code.Offset)) + if v != "" { + b = appendStructKey(ctx, code, b) + bb, err := appendNumber(ctx, b, v) + if err != nil { + return nil, err + } + b = appendStructEnd(ctx, code, bb) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndNumberString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = append(b, '"') + bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) + if err != nil { + return nil, err + } + b = append(bb, '"') + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyNumberString: + p := load(ctxptr, code.Idx) + v := ptrToNumber(p + uintptr(code.Offset)) + if v != "" { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + bb, err := appendNumber(ctx, b, v) + if err != nil { + return nil, err + } + b = append(bb, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndNumberPtr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyNumberPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = appendStructEnd(ctx, code, bb) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndNumberPtrString: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = append(bb, '"') + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyNumberPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = append(bb, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpEnd: + goto END + } + } +END: + return b, nil +} diff --git a/vendor/github.com/goccy/go-json/internal/encoder/vm_color/debug_vm.go b/vendor/github.com/goccy/go-json/internal/encoder/vm_color/debug_vm.go new file mode 100644 index 000000000..925f61ed8 --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/encoder/vm_color/debug_vm.go @@ -0,0 +1,35 @@ +package vm_color + +import ( + "fmt" + + "github.com/goccy/go-json/internal/encoder" +) + +func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) { + var code *encoder.Opcode + if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 { + code = codeSet.EscapeKeyCode + } else { + code = codeSet.NoescapeKeyCode + } + + defer func() { + if err := recover(); err != nil { + w := ctx.Option.DebugOut + fmt.Fprintln(w, "=============[DEBUG]===============") + fmt.Fprintln(w, "* [TYPE]") + fmt.Fprintln(w, codeSet.Type) + fmt.Fprintf(w, "\n") + fmt.Fprintln(w, "* [ALL OPCODE]") + fmt.Fprintln(w, code.Dump()) + fmt.Fprintf(w, "\n") + fmt.Fprintln(w, "* [CONTEXT]") + fmt.Fprintf(w, "%+v\n", ctx) + fmt.Fprintln(w, "===================================") + panic(err) + } + }() + + return Run(ctx, b, codeSet) +} diff --git a/vendor/github.com/goccy/go-json/internal/encoder/vm_color/hack.go b/vendor/github.com/goccy/go-json/internal/encoder/vm_color/hack.go new file mode 100644 index 000000000..12ec56c5b --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/encoder/vm_color/hack.go @@ -0,0 +1,9 @@ +package vm_color + +import ( + // HACK: compile order + // `vm`, `vm_indent`, `vm_color`, `vm_color_indent` packages uses a lot of memory to compile, + // so forcibly make dependencies and avoid compiling in concurrent. + // dependency order: vm => vm_indent => vm_color => vm_color_indent + _ "github.com/goccy/go-json/internal/encoder/vm_color_indent" +) diff --git a/vendor/github.com/goccy/go-json/internal/encoder/vm_color/util.go b/vendor/github.com/goccy/go-json/internal/encoder/vm_color/util.go new file mode 100644 index 000000000..33f29aee4 --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/encoder/vm_color/util.go @@ -0,0 +1,274 @@ +package vm_color + +import ( + "encoding/json" + "fmt" + "unsafe" + + "github.com/goccy/go-json/internal/encoder" + "github.com/goccy/go-json/internal/runtime" +) + +const uintptrSize = 4 << (^uintptr(0) >> 63) + +var ( + errUnsupportedValue = encoder.ErrUnsupportedValue + errUnsupportedFloat = encoder.ErrUnsupportedFloat + mapiterinit = encoder.MapIterInit + mapiterkey = encoder.MapIterKey + mapitervalue = encoder.MapIterValue + mapiternext = encoder.MapIterNext + maplen = encoder.MapLen +) + +type emptyInterface struct { + typ *runtime.Type + ptr unsafe.Pointer +} + +type nonEmptyInterface struct { + itab *struct { + ityp *runtime.Type // static interface type + typ *runtime.Type // dynamic concrete type + // unused fields... + } + ptr unsafe.Pointer +} + +func errUnimplementedOp(op encoder.OpType) error { + return fmt.Errorf("encoder: opcode %s has not been implemented", op) +} + +func load(base uintptr, idx uint32) uintptr { + addr := base + uintptr(idx) + return **(**uintptr)(unsafe.Pointer(&addr)) +} + +func store(base uintptr, idx uint32, p uintptr) { + addr := base + uintptr(idx) + **(**uintptr)(unsafe.Pointer(&addr)) = p +} + +func loadNPtr(base uintptr, idx uint32, ptrNum uint8) uintptr { + addr := base + uintptr(idx) + p := **(**uintptr)(unsafe.Pointer(&addr)) + for i := uint8(0); i < ptrNum; i++ { + if p == 0 { + return 0 + } + p = ptrToPtr(p) + } + return p +} + +func ptrToUint64(p uintptr, bitSize uint8) uint64 { + switch bitSize { + case 8: + return (uint64)(**(**uint8)(unsafe.Pointer(&p))) + case 16: + return (uint64)(**(**uint16)(unsafe.Pointer(&p))) + case 32: + return (uint64)(**(**uint32)(unsafe.Pointer(&p))) + case 64: + return **(**uint64)(unsafe.Pointer(&p)) + } + return 0 +} +func ptrToFloat32(p uintptr) float32 { return **(**float32)(unsafe.Pointer(&p)) } +func ptrToFloat64(p uintptr) float64 { return **(**float64)(unsafe.Pointer(&p)) } +func ptrToBool(p uintptr) bool { return **(**bool)(unsafe.Pointer(&p)) } +func ptrToBytes(p uintptr) []byte { return **(**[]byte)(unsafe.Pointer(&p)) } +func ptrToNumber(p uintptr) json.Number { return **(**json.Number)(unsafe.Pointer(&p)) } +func ptrToString(p uintptr) string { return **(**string)(unsafe.Pointer(&p)) } +func ptrToSlice(p uintptr) *runtime.SliceHeader { return *(**runtime.SliceHeader)(unsafe.Pointer(&p)) } +func ptrToPtr(p uintptr) uintptr { + return uintptr(**(**unsafe.Pointer)(unsafe.Pointer(&p))) +} +func ptrToNPtr(p uintptr, ptrNum uint8) uintptr { + for i := uint8(0); i < ptrNum; i++ { + if p == 0 { + return 0 + } + p = ptrToPtr(p) + } + return p +} + +func ptrToUnsafePtr(p uintptr) unsafe.Pointer { + return *(*unsafe.Pointer)(unsafe.Pointer(&p)) +} +func ptrToInterface(code *encoder.Opcode, p uintptr) interface{} { + return *(*interface{})(unsafe.Pointer(&emptyInterface{ + typ: code.Type, + ptr: *(*unsafe.Pointer)(unsafe.Pointer(&p)), + })) +} + +func appendInt(ctx *encoder.RuntimeContext, b []byte, p uintptr, code *encoder.Opcode) []byte { + format := ctx.Option.ColorScheme.Int + b = append(b, format.Header...) + b = encoder.AppendInt(ctx, b, p, code) + return append(b, format.Footer...) +} + +func appendUint(ctx *encoder.RuntimeContext, b []byte, p uintptr, code *encoder.Opcode) []byte { + format := ctx.Option.ColorScheme.Uint + b = append(b, format.Header...) + b = encoder.AppendUint(ctx, b, p, code) + return append(b, format.Footer...) +} + +func appendFloat32(ctx *encoder.RuntimeContext, b []byte, v float32) []byte { + format := ctx.Option.ColorScheme.Float + b = append(b, format.Header...) + b = encoder.AppendFloat32(ctx, b, v) + return append(b, format.Footer...) +} + +func appendFloat64(ctx *encoder.RuntimeContext, b []byte, v float64) []byte { + format := ctx.Option.ColorScheme.Float + b = append(b, format.Header...) + b = encoder.AppendFloat64(ctx, b, v) + return append(b, format.Footer...) +} + +func appendString(ctx *encoder.RuntimeContext, b []byte, v string) []byte { + format := ctx.Option.ColorScheme.String + b = append(b, format.Header...) + b = encoder.AppendString(ctx, b, v) + return append(b, format.Footer...) +} + +func appendByteSlice(ctx *encoder.RuntimeContext, b []byte, src []byte) []byte { + format := ctx.Option.ColorScheme.Binary + b = append(b, format.Header...) + b = encoder.AppendByteSlice(ctx, b, src) + return append(b, format.Footer...) +} + +func appendNumber(ctx *encoder.RuntimeContext, b []byte, n json.Number) ([]byte, error) { + format := ctx.Option.ColorScheme.Int + b = append(b, format.Header...) + bb, err := encoder.AppendNumber(ctx, b, n) + if err != nil { + return nil, err + } + return append(bb, format.Footer...), nil +} + +func appendBool(ctx *encoder.RuntimeContext, b []byte, v bool) []byte { + format := ctx.Option.ColorScheme.Bool + b = append(b, format.Header...) + if v { + b = append(b, "true"...) + } else { + b = append(b, "false"...) + } + return append(b, format.Footer...) +} + +func appendNull(ctx *encoder.RuntimeContext, b []byte) []byte { + format := ctx.Option.ColorScheme.Null + b = append(b, format.Header...) + b = append(b, "null"...) + return append(b, format.Footer...) +} + +func appendComma(_ *encoder.RuntimeContext, b []byte) []byte { + return append(b, ',') +} + +func appendNullComma(ctx *encoder.RuntimeContext, b []byte) []byte { + format := ctx.Option.ColorScheme.Null + b = append(b, format.Header...) + b = append(b, "null"...) + return append(append(b, format.Footer...), ',') +} + +func appendColon(_ *encoder.RuntimeContext, b []byte) []byte { + last := len(b) - 1 + b[last] = ':' + return b +} + +func appendMapKeyValue(_ *encoder.RuntimeContext, _ *encoder.Opcode, b, key, value []byte) []byte { + b = append(b, key[:len(key)-1]...) + b = append(b, ':') + return append(b, value...) +} + +func appendMapEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte { + last := len(b) - 1 + b[last] = '}' + b = append(b, ',') + return b +} + +func appendMarshalJSON(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte, v interface{}) ([]byte, error) { + return encoder.AppendMarshalJSON(ctx, code, b, v) +} + +func appendMarshalText(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte, v interface{}) ([]byte, error) { + format := ctx.Option.ColorScheme.String + b = append(b, format.Header...) + bb, err := encoder.AppendMarshalText(ctx, code, b, v) + if err != nil { + return nil, err + } + return append(bb, format.Footer...), nil +} + +func appendArrayHead(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte { + return append(b, '[') +} + +func appendArrayEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte { + last := len(b) - 1 + b[last] = ']' + return append(b, ',') +} + +func appendEmptyArray(_ *encoder.RuntimeContext, b []byte) []byte { + return append(b, '[', ']', ',') +} + +func appendEmptyObject(_ *encoder.RuntimeContext, b []byte) []byte { + return append(b, '{', '}', ',') +} + +func appendObjectEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte { + last := len(b) - 1 + b[last] = '}' + return append(b, ',') +} + +func appendStructHead(_ *encoder.RuntimeContext, b []byte) []byte { + return append(b, '{') +} + +func appendStructKey(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { + format := ctx.Option.ColorScheme.ObjectKey + b = append(b, format.Header...) + b = append(b, code.Key[:len(code.Key)-1]...) + b = append(b, format.Footer...) + + return append(b, ':') +} + +func appendStructEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte { + return append(b, '}', ',') +} + +func appendStructEndSkipLast(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { + last := len(b) - 1 + if b[last] == ',' { + b[last] = '}' + return appendComma(ctx, b) + } + return appendStructEnd(ctx, code, b) +} + +func restoreIndent(_ *encoder.RuntimeContext, _ *encoder.Opcode, _ uintptr) {} +func storeIndent(_ uintptr, _ *encoder.Opcode, _ uintptr) {} +func appendMapKeyIndent(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte { return b } +func appendArrayElemIndent(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte { return b } diff --git a/vendor/github.com/goccy/go-json/internal/encoder/vm_color/vm.go b/vendor/github.com/goccy/go-json/internal/encoder/vm_color/vm.go new file mode 100644 index 000000000..a63e83e55 --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/encoder/vm_color/vm.go @@ -0,0 +1,4859 @@ +// Code generated by internal/cmd/generator. DO NOT EDIT! +package vm_color + +import ( + "math" + "reflect" + "sort" + "unsafe" + + "github.com/goccy/go-json/internal/encoder" + "github.com/goccy/go-json/internal/runtime" +) + +func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) { + recursiveLevel := 0 + ptrOffset := uintptr(0) + ctxptr := ctx.Ptr() + var code *encoder.Opcode + if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 { + code = codeSet.EscapeKeyCode + } else { + code = codeSet.NoescapeKeyCode + } + + for { + switch code.Op { + default: + return nil, errUnimplementedOp(code.Op) + case encoder.OpPtr: + p := load(ctxptr, code.Idx) + code = code.Next + store(ctxptr, code.Idx, ptrToPtr(p)) + case encoder.OpIntPtr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpInt: + b = appendInt(ctx, b, load(ctxptr, code.Idx), code) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpUintPtr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpUint: + b = appendUint(ctx, b, load(ctxptr, code.Idx), code) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpIntString: + b = append(b, '"') + b = appendInt(ctx, b, load(ctxptr, code.Idx), code) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpUintString: + b = append(b, '"') + b = appendUint(ctx, b, load(ctxptr, code.Idx), code) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpFloat32Ptr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + b = appendComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpFloat32: + b = appendFloat32(ctx, b, ptrToFloat32(load(ctxptr, code.Idx))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpFloat64Ptr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpFloat64: + v := ptrToFloat64(load(ctxptr, code.Idx)) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStringPtr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpString: + b = appendString(ctx, b, ptrToString(load(ctxptr, code.Idx))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpBoolPtr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpBool: + b = appendBool(ctx, b, ptrToBool(load(ctxptr, code.Idx))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpBytesPtr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpBytes: + b = appendByteSlice(ctx, b, ptrToBytes(load(ctxptr, code.Idx))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpNumberPtr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpNumber: + bb, err := appendNumber(ctx, b, ptrToNumber(load(ctxptr, code.Idx))) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + code = code.Next + case encoder.OpInterfacePtr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpInterface: + p := load(ctxptr, code.Idx) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + if recursiveLevel > encoder.StartDetectingCyclesAfter { + for _, seen := range ctx.SeenPtr { + if p == seen { + return nil, errUnsupportedValue(code, p) + } + } + } + ctx.SeenPtr = append(ctx.SeenPtr, p) + var ( + typ *runtime.Type + ifacePtr unsafe.Pointer + ) + up := ptrToUnsafePtr(p) + if code.Flags&encoder.NonEmptyInterfaceFlags != 0 { + iface := (*nonEmptyInterface)(up) + ifacePtr = iface.ptr + if iface.itab != nil { + typ = iface.itab.typ + } + } else { + iface := (*emptyInterface)(up) + ifacePtr = iface.ptr + typ = iface.typ + } + if ifacePtr == nil { + isDirectedNil := typ != nil && typ.Kind() == reflect.Struct && !runtime.IfaceIndir(typ) + if !isDirectedNil { + b = appendNullComma(ctx, b) + code = code.Next + break + } + } + ctx.KeepRefs = append(ctx.KeepRefs, up) + ifaceCodeSet, err := encoder.CompileToGetCodeSet(ctx, uintptr(unsafe.Pointer(typ))) + if err != nil { + return nil, err + } + + totalLength := uintptr(code.Length) + 3 + nextTotalLength := uintptr(ifaceCodeSet.CodeLength) + 3 + + var c *encoder.Opcode + if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 { + c = ifaceCodeSet.InterfaceEscapeKeyCode + } else { + c = ifaceCodeSet.InterfaceNoescapeKeyCode + } + curlen := uintptr(len(ctx.Ptrs)) + offsetNum := ptrOffset / uintptrSize + oldOffset := ptrOffset + ptrOffset += totalLength * uintptrSize + oldBaseIndent := ctx.BaseIndent + ctx.BaseIndent += code.Indent + + newLen := offsetNum + totalLength + nextTotalLength + if curlen < newLen { + ctx.Ptrs = append(ctx.Ptrs, make([]uintptr, newLen-curlen)...) + } + ctxptr = ctx.Ptr() + ptrOffset // assign new ctxptr + + end := ifaceCodeSet.EndCode + store(ctxptr, c.Idx, uintptr(ifacePtr)) + store(ctxptr, end.Idx, oldOffset) + store(ctxptr, end.ElemIdx, uintptr(unsafe.Pointer(code.Next))) + storeIndent(ctxptr, end, uintptr(oldBaseIndent)) + code = c + recursiveLevel++ + case encoder.OpInterfaceEnd: + recursiveLevel-- + + // restore ctxptr + offset := load(ctxptr, code.Idx) + restoreIndent(ctx, code, ctxptr) + ctx.SeenPtr = ctx.SeenPtr[:len(ctx.SeenPtr)-1] + + codePtr := load(ctxptr, code.ElemIdx) + code = (*encoder.Opcode)(ptrToUnsafePtr(codePtr)) + ctxptr = ctx.Ptr() + offset + ptrOffset = offset + case encoder.OpMarshalJSONPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, ptrToPtr(p)) + fallthrough + case encoder.OpMarshalJSON: + p := load(ctxptr, code.Idx) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + if (code.Flags&encoder.IsNilableTypeFlags) != 0 && (code.Flags&encoder.IndirectFlags) != 0 { + p = ptrToPtr(p) + } + bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + code = code.Next + case encoder.OpMarshalTextPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, ptrToPtr(p)) + fallthrough + case encoder.OpMarshalText: + p := load(ctxptr, code.Idx) + if p == 0 { + b = append(b, `""`...) + b = appendComma(ctx, b) + code = code.Next + break + } + if (code.Flags&encoder.IsNilableTypeFlags) != 0 && (code.Flags&encoder.IndirectFlags) != 0 { + p = ptrToPtr(p) + } + bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + code = code.Next + case encoder.OpSlicePtr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.End.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpSlice: + p := load(ctxptr, code.Idx) + slice := ptrToSlice(p) + if p == 0 || slice.Data == nil { + b = appendNullComma(ctx, b) + code = code.End.Next + break + } + store(ctxptr, code.ElemIdx, 0) + store(ctxptr, code.Length, uintptr(slice.Len)) + store(ctxptr, code.Idx, uintptr(slice.Data)) + if slice.Len > 0 { + b = appendArrayHead(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, uintptr(slice.Data)) + } else { + b = appendEmptyArray(ctx, b) + code = code.End.Next + } + case encoder.OpSliceElem: + idx := load(ctxptr, code.ElemIdx) + length := load(ctxptr, code.Length) + idx++ + if idx < length { + b = appendArrayElemIndent(ctx, code, b) + store(ctxptr, code.ElemIdx, idx) + data := load(ctxptr, code.Idx) + size := uintptr(code.Size) + code = code.Next + store(ctxptr, code.Idx, data+idx*size) + } else { + b = appendArrayEnd(ctx, code, b) + code = code.End.Next + } + case encoder.OpArrayPtr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.End.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpArray: + p := load(ctxptr, code.Idx) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.End.Next + break + } + if code.Length > 0 { + b = appendArrayHead(ctx, code, b) + store(ctxptr, code.ElemIdx, 0) + code = code.Next + store(ctxptr, code.Idx, p) + } else { + b = appendEmptyArray(ctx, b) + code = code.End.Next + } + case encoder.OpArrayElem: + idx := load(ctxptr, code.ElemIdx) + idx++ + if idx < uintptr(code.Length) { + b = appendArrayElemIndent(ctx, code, b) + store(ctxptr, code.ElemIdx, idx) + p := load(ctxptr, code.Idx) + size := uintptr(code.Size) + code = code.Next + store(ctxptr, code.Idx, p+idx*size) + } else { + b = appendArrayEnd(ctx, code, b) + code = code.End.Next + } + case encoder.OpMapPtr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.End.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpMap: + p := load(ctxptr, code.Idx) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.End.Next + break + } + uptr := ptrToUnsafePtr(p) + mlen := maplen(uptr) + if mlen <= 0 { + b = appendEmptyObject(ctx, b) + code = code.End.Next + break + } + b = appendStructHead(ctx, b) + unorderedMap := (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 + mapCtx := encoder.NewMapContext(mlen, unorderedMap) + mapiterinit(code.Type, uptr, &mapCtx.Iter) + store(ctxptr, code.Idx, uintptr(unsafe.Pointer(mapCtx))) + ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(mapCtx)) + if unorderedMap { + b = appendMapKeyIndent(ctx, code.Next, b) + } else { + mapCtx.Start = len(b) + mapCtx.First = len(b) + } + key := mapiterkey(&mapCtx.Iter) + store(ctxptr, code.Next.Idx, uintptr(key)) + code = code.Next + case encoder.OpMapKey: + mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.Idx))) + idx := mapCtx.Idx + idx++ + if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 { + if idx < mapCtx.Len { + b = appendMapKeyIndent(ctx, code, b) + mapCtx.Idx = int(idx) + key := mapiterkey(&mapCtx.Iter) + store(ctxptr, code.Next.Idx, uintptr(key)) + code = code.Next + } else { + b = appendObjectEnd(ctx, code, b) + encoder.ReleaseMapContext(mapCtx) + code = code.End.Next + } + } else { + mapCtx.Slice.Items[mapCtx.Idx].Value = b[mapCtx.Start:len(b)] + if idx < mapCtx.Len { + mapCtx.Idx = int(idx) + mapCtx.Start = len(b) + key := mapiterkey(&mapCtx.Iter) + store(ctxptr, code.Next.Idx, uintptr(key)) + code = code.Next + } else { + code = code.End + } + } + case encoder.OpMapValue: + mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.Idx))) + if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 { + b = appendColon(ctx, b) + } else { + mapCtx.Slice.Items[mapCtx.Idx].Key = b[mapCtx.Start:len(b)] + mapCtx.Start = len(b) + } + value := mapitervalue(&mapCtx.Iter) + store(ctxptr, code.Next.Idx, uintptr(value)) + mapiternext(&mapCtx.Iter) + code = code.Next + case encoder.OpMapEnd: + // this operation only used by sorted map. + mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.Idx))) + sort.Sort(mapCtx.Slice) + buf := mapCtx.Buf + for _, item := range mapCtx.Slice.Items { + buf = appendMapKeyValue(ctx, code, buf, item.Key, item.Value) + } + buf = appendMapEnd(ctx, code, buf) + b = b[:mapCtx.First] + b = append(b, buf...) + mapCtx.Buf = buf + encoder.ReleaseMapContext(mapCtx) + code = code.Next + case encoder.OpRecursivePtr: + p := load(ctxptr, code.Idx) + if p == 0 { + code = code.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpRecursive: + ptr := load(ctxptr, code.Idx) + if ptr != 0 { + if recursiveLevel > encoder.StartDetectingCyclesAfter { + for _, seen := range ctx.SeenPtr { + if ptr == seen { + return nil, errUnsupportedValue(code, ptr) + } + } + } + } + ctx.SeenPtr = append(ctx.SeenPtr, ptr) + c := code.Jmp.Code + curlen := uintptr(len(ctx.Ptrs)) + offsetNum := ptrOffset / uintptrSize + oldOffset := ptrOffset + ptrOffset += code.Jmp.CurLen * uintptrSize + oldBaseIndent := ctx.BaseIndent + indentDiffFromTop := c.Indent - 1 + ctx.BaseIndent += code.Indent - indentDiffFromTop + + newLen := offsetNum + code.Jmp.CurLen + code.Jmp.NextLen + if curlen < newLen { + ctx.Ptrs = append(ctx.Ptrs, make([]uintptr, newLen-curlen)...) + } + ctxptr = ctx.Ptr() + ptrOffset // assign new ctxptr + + store(ctxptr, c.Idx, ptr) + store(ctxptr, c.End.Next.Idx, oldOffset) + store(ctxptr, c.End.Next.ElemIdx, uintptr(unsafe.Pointer(code.Next))) + storeIndent(ctxptr, c.End.Next, uintptr(oldBaseIndent)) + code = c + recursiveLevel++ + case encoder.OpRecursiveEnd: + recursiveLevel-- + + // restore ctxptr + restoreIndent(ctx, code, ctxptr) + offset := load(ctxptr, code.Idx) + ctx.SeenPtr = ctx.SeenPtr[:len(ctx.SeenPtr)-1] + + codePtr := load(ctxptr, code.ElemIdx) + code = (*encoder.Opcode)(ptrToUnsafePtr(codePtr)) + ctxptr = ctx.Ptr() + offset + ptrOffset = offset + case encoder.OpStructPtrHead: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHead: + p := load(ctxptr, code.Idx) + if p == 0 && ((code.Flags&encoder.IndirectFlags) != 0 || code.Next.Op == encoder.OpStructEnd) { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if len(code.Key) > 0 { + if (code.Flags&encoder.IsTaggedKeyFlags) != 0 || code.Flags&encoder.AnonymousKeyFlags == 0 { + b = appendStructKey(ctx, code, b) + } + } + p += uintptr(code.Offset) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructPtrHeadOmitEmpty: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmpty: + p := load(ctxptr, code.Idx) + if p == 0 && ((code.Flags&encoder.IndirectFlags) != 0 || code.Next.Op == encoder.OpStructEnd) { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + p += uintptr(code.Offset) + if p == 0 || (ptrToPtr(p) == 0 && (code.Flags&encoder.IsNextOpPtrTypeFlags) != 0) { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructPtrHeadInt: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadInt: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyInt: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyInt: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadIntString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadIntString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyIntString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyIntString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + p += uintptr(code.Offset) + u64 := ptrToUint64(p, code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendInt(ctx, b, p, code) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadIntPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadIntPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendInt(ctx, b, p, code) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyIntPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyIntPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendInt(ctx, b, p, code) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadIntPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadIntPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendInt(ctx, b, p, code) + b = append(b, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyIntPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyIntPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendInt(ctx, b, p, code) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadUint: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadUint: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyUint: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyUint: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadUintString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadUintString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyUintString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyUintString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadUintPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadUintPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendUint(ctx, b, p, code) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyUintPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyUintPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendUint(ctx, b, p, code) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadUintPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadUintPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendUint(ctx, b, p, code) + b = append(b, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyUintPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyUintPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendUint(ctx, b, p, code) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadFloat32: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadFloat32: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyFloat32: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyFloat32: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToFloat32(p + uintptr(code.Offset)) + if v == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + b = appendFloat32(ctx, b, v) + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadFloat32String: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadFloat32String: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyFloat32String: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyFloat32String: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToFloat32(p + uintptr(code.Offset)) + if v == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat32(ctx, b, v) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadFloat32Ptr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadFloat32Ptr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendFloat32(ctx, b, ptrToFloat32(p)) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyFloat32Ptr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyFloat32Ptr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendFloat32(ctx, b, ptrToFloat32(p)) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadFloat32PtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadFloat32PtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendFloat32(ctx, b, ptrToFloat32(p)) + b = append(b, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyFloat32PtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyFloat32PtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat32(ctx, b, ptrToFloat32(p)) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadFloat64: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadFloat64: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + v := ptrToFloat64(p + uintptr(code.Offset)) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = appendFloat64(ctx, b, v) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyFloat64: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyFloat64: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToFloat64(p + uintptr(code.Offset)) + if v == 0 { + code = code.NextField + } else { + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendStructKey(ctx, code, b) + b = appendFloat64(ctx, b, v) + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadFloat64String: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadFloat64String: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToFloat64(p + uintptr(code.Offset)) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat64(ctx, b, v) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyFloat64String: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyFloat64String: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToFloat64(p + uintptr(code.Offset)) + if v == 0 { + code = code.NextField + } else { + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat64(ctx, b, v) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadFloat64Ptr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadFloat64Ptr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyFloat64Ptr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyFloat64Ptr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadFloat64PtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadFloat64PtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = append(b, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyFloat64PtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyFloat64PtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNull(ctx, b) + b = appendComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, ptrToString(p+uintptr(code.Offset))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToString(p + uintptr(code.Offset)) + if v == "" { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, v) + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadStringString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadStringString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p+uintptr(code.Offset))))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyStringString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyStringString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToString(p + uintptr(code.Offset)) + if v == "" { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, string(appendString(ctx, []byte{}, v))) + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadStringPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadStringPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendString(ctx, b, ptrToString(p)) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyStringPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyStringPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, ptrToString(p)) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadStringPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadStringPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyStringPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyStringPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadBool: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadBool: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyBool: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyBool: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToBool(p + uintptr(code.Offset)) + if v { + b = appendStructKey(ctx, code, b) + b = appendBool(ctx, b, v) + b = appendComma(ctx, b) + code = code.Next + } else { + code = code.NextField + } + case encoder.OpStructPtrHeadBoolString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadBoolString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyBoolString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyBoolString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToBool(p + uintptr(code.Offset)) + if v { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendBool(ctx, b, v) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + } else { + code = code.NextField + } + case encoder.OpStructPtrHeadBoolPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadBoolPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendBool(ctx, b, ptrToBool(p)) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyBoolPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyBoolPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendBool(ctx, b, ptrToBool(p)) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadBoolPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadBoolPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendBool(ctx, b, ptrToBool(p)) + b = append(b, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyBoolPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyBoolPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendBool(ctx, b, ptrToBool(p)) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadBytes: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadBytes: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = appendByteSlice(ctx, b, ptrToBytes(p+uintptr(code.Offset))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyBytes: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyBytes: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToBytes(p + uintptr(code.Offset)) + if len(v) == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + b = appendByteSlice(ctx, b, v) + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadBytesPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadBytesPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendByteSlice(ctx, b, ptrToBytes(p)) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyBytesPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyBytesPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendByteSlice(ctx, b, ptrToBytes(p)) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadNumber: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadNumber: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyNumber: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyNumber: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToNumber(p + uintptr(code.Offset)) + if v == "" { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + bb, err := appendNumber(ctx, b, v) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + code = code.Next + } + case encoder.OpStructPtrHeadNumberString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadNumberString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) + if err != nil { + return nil, err + } + b = append(bb, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyNumberString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyNumberString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToNumber(p + uintptr(code.Offset)) + if v == "" { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + bb, err := appendNumber(ctx, b, v) + if err != nil { + return nil, err + } + b = append(bb, '"') + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadNumberPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadNumberPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyNumberPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyNumberPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + } + code = code.Next + case encoder.OpStructPtrHeadNumberPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadNumberPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = append(bb, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyNumberPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyNumberPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = append(bb, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadArray, encoder.OpStructPtrHeadSlice: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadArray, encoder.OpStructHeadSlice: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + p += uintptr(code.Offset) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructPtrHeadOmitEmptyArray: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyArray: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + p += uintptr(code.Offset) + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructPtrHeadOmitEmptySlice: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptySlice: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + p += uintptr(code.Offset) + slice := ptrToSlice(p) + if slice.Len == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructPtrHeadArrayPtr, encoder.OpStructPtrHeadSlicePtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadArrayPtr, encoder.OpStructHeadSlicePtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNullComma(ctx, b) + code = code.NextField + } else { + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructPtrHeadOmitEmptyArrayPtr, encoder.OpStructPtrHeadOmitEmptySlicePtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyArrayPtr, encoder.OpStructHeadOmitEmptySlicePtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructPtrHeadMap: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadMap: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if p != 0 && (code.Flags&encoder.IndirectFlags) != 0 { + p = ptrToPtr(p + uintptr(code.Offset)) + } + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructPtrHeadOmitEmptyMap: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyMap: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if p != 0 && (code.Flags&encoder.IndirectFlags) != 0 { + p = ptrToPtr(p + uintptr(code.Offset)) + } + if maplen(ptrToUnsafePtr(p)) == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructPtrHeadMapPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadMapPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.NextField + break + } + p = ptrToPtr(p + uintptr(code.Offset)) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.NextField + } else { + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p, code.PtrNum) + } + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructPtrHeadOmitEmptyMapPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyMapPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if p == 0 { + code = code.NextField + break + } + p = ptrToPtr(p + uintptr(code.Offset)) + if p == 0 { + code = code.NextField + } else { + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p, code.PtrNum) + } + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructPtrHeadMarshalJSON: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if (code.Flags & encoder.IndirectFlags) != 0 { + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadMarshalJSON: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + p += uintptr(code.Offset) + if (code.Flags & encoder.IsNilableTypeFlags) != 0 { + if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadMarshalJSON { + p = ptrToPtr(p) + } + } + if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyMarshalJSON: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if (code.Flags & encoder.IndirectFlags) != 0 { + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyMarshalJSON: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + p += uintptr(code.Offset) + if (code.Flags & encoder.IsNilableTypeFlags) != 0 { + if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadOmitEmptyMarshalJSON { + p = ptrToPtr(p) + } + } + iface := ptrToInterface(code, p) + if (code.Flags&encoder.NilCheckFlags) != 0 && encoder.IsNilForMarshaler(iface) { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + bb, err := appendMarshalJSON(ctx, code, b, iface) + if err != nil { + return nil, err + } + b = bb + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadMarshalJSONPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadMarshalJSONPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyMarshalJSONPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyMarshalJSONPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if p == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadMarshalText: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if (code.Flags & encoder.IndirectFlags) != 0 { + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadMarshalText: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + p += uintptr(code.Offset) + if (code.Flags & encoder.IsNilableTypeFlags) != 0 { + if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadMarshalText { + p = ptrToPtr(p) + } + } + if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyMarshalText: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if (code.Flags & encoder.IndirectFlags) != 0 { + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyMarshalText: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + p += uintptr(code.Offset) + if (code.Flags & encoder.IsNilableTypeFlags) != 0 { + if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadOmitEmptyMarshalText { + p = ptrToPtr(p) + } + } + if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadMarshalTextPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadMarshalTextPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyMarshalTextPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyMarshalTextPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if p == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructField: + if code.Flags&encoder.IsTaggedKeyFlags != 0 || code.Flags&encoder.AnonymousKeyFlags == 0 { + b = appendStructKey(ctx, code, b) + } + p := load(ctxptr, code.Idx) + uintptr(code.Offset) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructFieldOmitEmpty: + p := load(ctxptr, code.Idx) + p += uintptr(code.Offset) + if ptrToPtr(p) == 0 && (code.Flags&encoder.IsNextOpPtrTypeFlags) != 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructFieldInt: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyInt: + p := load(ctxptr, code.Idx) + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldIntString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyIntString: + p := load(ctxptr, code.Idx) + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldIntPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendInt(ctx, b, p, code) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyIntPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendInt(ctx, b, p, code) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldIntPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendInt(ctx, b, p, code) + b = append(b, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyIntPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendInt(ctx, b, p, code) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldUint: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyUint: + p := load(ctxptr, code.Idx) + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldUintString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyUintString: + p := load(ctxptr, code.Idx) + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldUintPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendUint(ctx, b, p, code) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyUintPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendUint(ctx, b, p, code) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldUintPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendUint(ctx, b, p, code) + b = append(b, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyUintPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendUint(ctx, b, p, code) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldFloat32: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyFloat32: + p := load(ctxptr, code.Idx) + v := ptrToFloat32(p + uintptr(code.Offset)) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = appendFloat32(ctx, b, v) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldFloat32String: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyFloat32String: + p := load(ctxptr, code.Idx) + v := ptrToFloat32(p + uintptr(code.Offset)) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat32(ctx, b, v) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldFloat32Ptr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendFloat32(ctx, b, ptrToFloat32(p)) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyFloat32Ptr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendFloat32(ctx, b, ptrToFloat32(p)) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldFloat32PtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendFloat32(ctx, b, ptrToFloat32(p)) + b = append(b, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyFloat32PtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat32(ctx, b, ptrToFloat32(p)) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldFloat64: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + v := ptrToFloat64(p + uintptr(code.Offset)) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyFloat64: + p := load(ctxptr, code.Idx) + v := ptrToFloat64(p + uintptr(code.Offset)) + if v != 0 { + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendStructKey(ctx, code, b) + b = appendFloat64(ctx, b, v) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldFloat64String: + p := load(ctxptr, code.Idx) + v := ptrToFloat64(p + uintptr(code.Offset)) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat64(ctx, b, v) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyFloat64String: + p := load(ctxptr, code.Idx) + v := ptrToFloat64(p + uintptr(code.Offset)) + if v != 0 { + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat64(ctx, b, v) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldFloat64Ptr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyFloat64Ptr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldFloat64PtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = append(b, '"') + b = appendFloat64(ctx, b, v) + b = append(b, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyFloat64PtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, ptrToString(p+uintptr(code.Offset))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyString: + p := load(ctxptr, code.Idx) + v := ptrToString(p + uintptr(code.Offset)) + if v != "" { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, v) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldStringString: + p := load(ctxptr, code.Idx) + s := ptrToString(p + uintptr(code.Offset)) + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, string(appendString(ctx, []byte{}, s))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyStringString: + p := load(ctxptr, code.Idx) + v := ptrToString(p + uintptr(code.Offset)) + if v != "" { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, string(appendString(ctx, []byte{}, v))) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldStringPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendString(ctx, b, ptrToString(p)) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyStringPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, ptrToString(p)) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldStringPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyStringPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldBool: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyBool: + p := load(ctxptr, code.Idx) + v := ptrToBool(p + uintptr(code.Offset)) + if v { + b = appendStructKey(ctx, code, b) + b = appendBool(ctx, b, v) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldBoolString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyBoolString: + p := load(ctxptr, code.Idx) + v := ptrToBool(p + uintptr(code.Offset)) + if v { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendBool(ctx, b, v) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldBoolPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendBool(ctx, b, ptrToBool(p)) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyBoolPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendBool(ctx, b, ptrToBool(p)) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldBoolPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendBool(ctx, b, ptrToBool(p)) + b = append(b, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyBoolPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendBool(ctx, b, ptrToBool(p)) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldBytes: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendByteSlice(ctx, b, ptrToBytes(p+uintptr(code.Offset))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyBytes: + p := load(ctxptr, code.Idx) + v := ptrToBytes(p + uintptr(code.Offset)) + if len(v) > 0 { + b = appendStructKey(ctx, code, b) + b = appendByteSlice(ctx, b, v) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldBytesPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendByteSlice(ctx, b, ptrToBytes(p)) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyBytesPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendByteSlice(ctx, b, ptrToBytes(p)) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldNumber: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + code = code.Next + case encoder.OpStructFieldOmitEmptyNumber: + p := load(ctxptr, code.Idx) + v := ptrToNumber(p + uintptr(code.Offset)) + if v != "" { + b = appendStructKey(ctx, code, b) + bb, err := appendNumber(ctx, b, v) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + } + code = code.Next + case encoder.OpStructFieldNumberString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = append(b, '"') + bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) + if err != nil { + return nil, err + } + b = append(bb, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyNumberString: + p := load(ctxptr, code.Idx) + v := ptrToNumber(p + uintptr(code.Offset)) + if v != "" { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + bb, err := appendNumber(ctx, b, v) + if err != nil { + return nil, err + } + b = append(bb, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldNumberPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyNumberPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + } + code = code.Next + case encoder.OpStructFieldNumberPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = append(bb, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyNumberPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = append(bb, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldMarshalJSON: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + p += uintptr(code.Offset) + if (code.Flags & encoder.IsNilableTypeFlags) != 0 { + p = ptrToPtr(p) + } + if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyMarshalJSON: + p := load(ctxptr, code.Idx) + p += uintptr(code.Offset) + if (code.Flags & encoder.IsNilableTypeFlags) != 0 { + p = ptrToPtr(p) + } + if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { + code = code.NextField + break + } + iface := ptrToInterface(code, p) + if (code.Flags&encoder.NilCheckFlags) != 0 && encoder.IsNilForMarshaler(iface) { + code = code.NextField + break + } + b = appendStructKey(ctx, code, b) + bb, err := appendMarshalJSON(ctx, code, b, iface) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + code = code.Next + case encoder.OpStructFieldMarshalJSONPtr: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyMarshalJSONPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + } + code = code.Next + case encoder.OpStructFieldMarshalText: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + p += uintptr(code.Offset) + if (code.Flags & encoder.IsNilableTypeFlags) != 0 { + p = ptrToPtr(p) + } + if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyMarshalText: + p := load(ctxptr, code.Idx) + p += uintptr(code.Offset) + if (code.Flags & encoder.IsNilableTypeFlags) != 0 { + p = ptrToPtr(p) + } + if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { + code = code.NextField + break + } + b = appendStructKey(ctx, code, b) + bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + code = code.Next + case encoder.OpStructFieldMarshalTextPtr: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyMarshalTextPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + } + code = code.Next + case encoder.OpStructFieldArray: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p += uintptr(code.Offset) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructFieldOmitEmptyArray: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p += uintptr(code.Offset) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructFieldArrayPtr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructFieldOmitEmptyArrayPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } else { + code = code.NextField + } + case encoder.OpStructFieldSlice: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p += uintptr(code.Offset) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructFieldOmitEmptySlice: + p := load(ctxptr, code.Idx) + p += uintptr(code.Offset) + slice := ptrToSlice(p) + if slice.Len == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructFieldSlicePtr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructFieldOmitEmptySlicePtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } else { + code = code.NextField + } + case encoder.OpStructFieldMap: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToPtr(p + uintptr(code.Offset)) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructFieldOmitEmptyMap: + p := load(ctxptr, code.Idx) + p = ptrToPtr(p + uintptr(code.Offset)) + if p == 0 || maplen(ptrToUnsafePtr(p)) == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructFieldMapPtr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToPtr(p + uintptr(code.Offset)) + if p != 0 { + p = ptrToNPtr(p, code.PtrNum) + } + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructFieldOmitEmptyMapPtr: + p := load(ctxptr, code.Idx) + p = ptrToPtr(p + uintptr(code.Offset)) + if p != 0 { + p = ptrToNPtr(p, code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } else { + code = code.NextField + } + case encoder.OpStructFieldStruct: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p += uintptr(code.Offset) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructFieldOmitEmptyStruct: + p := load(ctxptr, code.Idx) + p += uintptr(code.Offset) + if ptrToPtr(p) == 0 && (code.Flags&encoder.IsNextOpPtrTypeFlags) != 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructEnd: + b = appendStructEndSkipLast(ctx, code, b) + code = code.Next + case encoder.OpStructEndInt: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyInt: + p := load(ctxptr, code.Idx) + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndIntString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyIntString: + p := load(ctxptr, code.Idx) + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndIntPtr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendInt(ctx, b, p, code) + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyIntPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendInt(ctx, b, p, code) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndIntPtrString: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendInt(ctx, b, p, code) + b = append(b, '"') + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyIntPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendInt(ctx, b, p, code) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndUint: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyUint: + p := load(ctxptr, code.Idx) + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndUintString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyUintString: + p := load(ctxptr, code.Idx) + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndUintPtr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendUint(ctx, b, p, code) + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyUintPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendUint(ctx, b, p, code) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndUintPtrString: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendUint(ctx, b, p, code) + b = append(b, '"') + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyUintPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendUint(ctx, b, p, code) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndFloat32: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyFloat32: + p := load(ctxptr, code.Idx) + v := ptrToFloat32(p + uintptr(code.Offset)) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = appendFloat32(ctx, b, v) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndFloat32String: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyFloat32String: + p := load(ctxptr, code.Idx) + v := ptrToFloat32(p + uintptr(code.Offset)) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat32(ctx, b, v) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndFloat32Ptr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendFloat32(ctx, b, ptrToFloat32(p)) + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyFloat32Ptr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendFloat32(ctx, b, ptrToFloat32(p)) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndFloat32PtrString: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendFloat32(ctx, b, ptrToFloat32(p)) + b = append(b, '"') + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyFloat32PtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat32(ctx, b, ptrToFloat32(p)) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndFloat64: + p := load(ctxptr, code.Idx) + v := ptrToFloat64(p + uintptr(code.Offset)) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendStructKey(ctx, code, b) + b = appendFloat64(ctx, b, v) + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyFloat64: + p := load(ctxptr, code.Idx) + v := ptrToFloat64(p + uintptr(code.Offset)) + if v != 0 { + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendStructKey(ctx, code, b) + b = appendFloat64(ctx, b, v) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndFloat64String: + p := load(ctxptr, code.Idx) + v := ptrToFloat64(p + uintptr(code.Offset)) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat64(ctx, b, v) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyFloat64String: + p := load(ctxptr, code.Idx) + v := ptrToFloat64(p + uintptr(code.Offset)) + if v != 0 { + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat64(ctx, b, v) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndFloat64Ptr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + b = appendStructEnd(ctx, code, b) + code = code.Next + break + } + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyFloat64Ptr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndFloat64PtrString: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = append(b, '"') + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyFloat64PtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = append(b, '"') + b = appendFloat64(ctx, b, v) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, ptrToString(p+uintptr(code.Offset))) + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyString: + p := load(ctxptr, code.Idx) + v := ptrToString(p + uintptr(code.Offset)) + if v != "" { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, v) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndStringString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + s := ptrToString(p + uintptr(code.Offset)) + b = appendString(ctx, b, string(appendString(ctx, []byte{}, s))) + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyStringString: + p := load(ctxptr, code.Idx) + v := ptrToString(p + uintptr(code.Offset)) + if v != "" { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, string(appendString(ctx, []byte{}, v))) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndStringPtr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendString(ctx, b, ptrToString(p)) + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyStringPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, ptrToString(p)) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndStringPtrString: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyStringPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndBool: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyBool: + p := load(ctxptr, code.Idx) + v := ptrToBool(p + uintptr(code.Offset)) + if v { + b = appendStructKey(ctx, code, b) + b = appendBool(ctx, b, v) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndBoolString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyBoolString: + p := load(ctxptr, code.Idx) + v := ptrToBool(p + uintptr(code.Offset)) + if v { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendBool(ctx, b, v) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndBoolPtr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendBool(ctx, b, ptrToBool(p)) + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyBoolPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendBool(ctx, b, ptrToBool(p)) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndBoolPtrString: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendBool(ctx, b, ptrToBool(p)) + b = append(b, '"') + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyBoolPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendBool(ctx, b, ptrToBool(p)) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndBytes: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendByteSlice(ctx, b, ptrToBytes(p+uintptr(code.Offset))) + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyBytes: + p := load(ctxptr, code.Idx) + v := ptrToBytes(p + uintptr(code.Offset)) + if len(v) > 0 { + b = appendStructKey(ctx, code, b) + b = appendByteSlice(ctx, b, v) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndBytesPtr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendByteSlice(ctx, b, ptrToBytes(p)) + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyBytesPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendByteSlice(ctx, b, ptrToBytes(p)) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndNumber: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) + if err != nil { + return nil, err + } + b = appendStructEnd(ctx, code, bb) + code = code.Next + case encoder.OpStructEndOmitEmptyNumber: + p := load(ctxptr, code.Idx) + v := ptrToNumber(p + uintptr(code.Offset)) + if v != "" { + b = appendStructKey(ctx, code, b) + bb, err := appendNumber(ctx, b, v) + if err != nil { + return nil, err + } + b = appendStructEnd(ctx, code, bb) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndNumberString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = append(b, '"') + bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) + if err != nil { + return nil, err + } + b = append(bb, '"') + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyNumberString: + p := load(ctxptr, code.Idx) + v := ptrToNumber(p + uintptr(code.Offset)) + if v != "" { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + bb, err := appendNumber(ctx, b, v) + if err != nil { + return nil, err + } + b = append(bb, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndNumberPtr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyNumberPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = appendStructEnd(ctx, code, bb) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndNumberPtrString: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = append(bb, '"') + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyNumberPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = append(bb, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpEnd: + goto END + } + } +END: + return b, nil +} diff --git a/vendor/github.com/goccy/go-json/internal/encoder/vm_color_indent/debug_vm.go b/vendor/github.com/goccy/go-json/internal/encoder/vm_color_indent/debug_vm.go new file mode 100644 index 000000000..dd4cd489e --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/encoder/vm_color_indent/debug_vm.go @@ -0,0 +1,35 @@ +package vm_color_indent + +import ( + "fmt" + + "github.com/goccy/go-json/internal/encoder" +) + +func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) { + var code *encoder.Opcode + if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 { + code = codeSet.EscapeKeyCode + } else { + code = codeSet.NoescapeKeyCode + } + + defer func() { + if err := recover(); err != nil { + w := ctx.Option.DebugOut + fmt.Fprintln(w, "=============[DEBUG]===============") + fmt.Fprintln(w, "* [TYPE]") + fmt.Fprintln(w, codeSet.Type) + fmt.Fprintf(w, "\n") + fmt.Fprintln(w, "* [ALL OPCODE]") + fmt.Fprintln(w, code.Dump()) + fmt.Fprintf(w, "\n") + fmt.Fprintln(w, "* [CONTEXT]") + fmt.Fprintf(w, "%+v\n", ctx) + fmt.Fprintln(w, "===================================") + panic(err) + } + }() + + return Run(ctx, b, codeSet) +} diff --git a/vendor/github.com/goccy/go-json/internal/encoder/vm_color_indent/util.go b/vendor/github.com/goccy/go-json/internal/encoder/vm_color_indent/util.go new file mode 100644 index 000000000..2395abec9 --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/encoder/vm_color_indent/util.go @@ -0,0 +1,297 @@ +package vm_color_indent + +import ( + "encoding/json" + "fmt" + "unsafe" + + "github.com/goccy/go-json/internal/encoder" + "github.com/goccy/go-json/internal/runtime" +) + +const uintptrSize = 4 << (^uintptr(0) >> 63) + +var ( + appendIndent = encoder.AppendIndent + appendStructEnd = encoder.AppendStructEndIndent + errUnsupportedValue = encoder.ErrUnsupportedValue + errUnsupportedFloat = encoder.ErrUnsupportedFloat + mapiterinit = encoder.MapIterInit + mapiterkey = encoder.MapIterKey + mapitervalue = encoder.MapIterValue + mapiternext = encoder.MapIterNext + maplen = encoder.MapLen +) + +type emptyInterface struct { + typ *runtime.Type + ptr unsafe.Pointer +} + +type nonEmptyInterface struct { + itab *struct { + ityp *runtime.Type // static interface type + typ *runtime.Type // dynamic concrete type + // unused fields... + } + ptr unsafe.Pointer +} + +func errUnimplementedOp(op encoder.OpType) error { + return fmt.Errorf("encoder (indent): opcode %s has not been implemented", op) +} + +func load(base uintptr, idx uint32) uintptr { + addr := base + uintptr(idx) + return **(**uintptr)(unsafe.Pointer(&addr)) +} + +func store(base uintptr, idx uint32, p uintptr) { + addr := base + uintptr(idx) + **(**uintptr)(unsafe.Pointer(&addr)) = p +} + +func loadNPtr(base uintptr, idx uint32, ptrNum uint8) uintptr { + addr := base + uintptr(idx) + p := **(**uintptr)(unsafe.Pointer(&addr)) + for i := uint8(0); i < ptrNum; i++ { + if p == 0 { + return 0 + } + p = ptrToPtr(p) + } + return p +} + +func ptrToUint64(p uintptr, bitSize uint8) uint64 { + switch bitSize { + case 8: + return (uint64)(**(**uint8)(unsafe.Pointer(&p))) + case 16: + return (uint64)(**(**uint16)(unsafe.Pointer(&p))) + case 32: + return (uint64)(**(**uint32)(unsafe.Pointer(&p))) + case 64: + return **(**uint64)(unsafe.Pointer(&p)) + } + return 0 +} + +func ptrToFloat32(p uintptr) float32 { return **(**float32)(unsafe.Pointer(&p)) } +func ptrToFloat64(p uintptr) float64 { return **(**float64)(unsafe.Pointer(&p)) } +func ptrToBool(p uintptr) bool { return **(**bool)(unsafe.Pointer(&p)) } +func ptrToBytes(p uintptr) []byte { return **(**[]byte)(unsafe.Pointer(&p)) } +func ptrToNumber(p uintptr) json.Number { return **(**json.Number)(unsafe.Pointer(&p)) } +func ptrToString(p uintptr) string { return **(**string)(unsafe.Pointer(&p)) } +func ptrToSlice(p uintptr) *runtime.SliceHeader { return *(**runtime.SliceHeader)(unsafe.Pointer(&p)) } +func ptrToPtr(p uintptr) uintptr { + return uintptr(**(**unsafe.Pointer)(unsafe.Pointer(&p))) +} +func ptrToNPtr(p uintptr, ptrNum uint8) uintptr { + for i := uint8(0); i < ptrNum; i++ { + if p == 0 { + return 0 + } + p = ptrToPtr(p) + } + return p +} + +func ptrToUnsafePtr(p uintptr) unsafe.Pointer { + return *(*unsafe.Pointer)(unsafe.Pointer(&p)) +} +func ptrToInterface(code *encoder.Opcode, p uintptr) interface{} { + return *(*interface{})(unsafe.Pointer(&emptyInterface{ + typ: code.Type, + ptr: *(*unsafe.Pointer)(unsafe.Pointer(&p)), + })) +} + +func appendInt(ctx *encoder.RuntimeContext, b []byte, p uintptr, code *encoder.Opcode) []byte { + format := ctx.Option.ColorScheme.Int + b = append(b, format.Header...) + b = encoder.AppendInt(ctx, b, p, code) + return append(b, format.Footer...) +} + +func appendUint(ctx *encoder.RuntimeContext, b []byte, p uintptr, code *encoder.Opcode) []byte { + format := ctx.Option.ColorScheme.Uint + b = append(b, format.Header...) + b = encoder.AppendUint(ctx, b, p, code) + return append(b, format.Footer...) +} + +func appendFloat32(ctx *encoder.RuntimeContext, b []byte, v float32) []byte { + format := ctx.Option.ColorScheme.Float + b = append(b, format.Header...) + b = encoder.AppendFloat32(ctx, b, v) + return append(b, format.Footer...) +} + +func appendFloat64(ctx *encoder.RuntimeContext, b []byte, v float64) []byte { + format := ctx.Option.ColorScheme.Float + b = append(b, format.Header...) + b = encoder.AppendFloat64(ctx, b, v) + return append(b, format.Footer...) +} + +func appendString(ctx *encoder.RuntimeContext, b []byte, v string) []byte { + format := ctx.Option.ColorScheme.String + b = append(b, format.Header...) + b = encoder.AppendString(ctx, b, v) + return append(b, format.Footer...) +} + +func appendByteSlice(ctx *encoder.RuntimeContext, b []byte, src []byte) []byte { + format := ctx.Option.ColorScheme.Binary + b = append(b, format.Header...) + b = encoder.AppendByteSlice(ctx, b, src) + return append(b, format.Footer...) +} + +func appendNumber(ctx *encoder.RuntimeContext, b []byte, n json.Number) ([]byte, error) { + format := ctx.Option.ColorScheme.Int + b = append(b, format.Header...) + bb, err := encoder.AppendNumber(ctx, b, n) + if err != nil { + return nil, err + } + return append(bb, format.Footer...), nil +} + +func appendBool(ctx *encoder.RuntimeContext, b []byte, v bool) []byte { + format := ctx.Option.ColorScheme.Bool + b = append(b, format.Header...) + if v { + b = append(b, "true"...) + } else { + b = append(b, "false"...) + } + return append(b, format.Footer...) +} + +func appendNull(ctx *encoder.RuntimeContext, b []byte) []byte { + format := ctx.Option.ColorScheme.Null + b = append(b, format.Header...) + b = append(b, "null"...) + return append(b, format.Footer...) +} + +func appendComma(_ *encoder.RuntimeContext, b []byte) []byte { + return append(b, ',', '\n') +} + +func appendNullComma(ctx *encoder.RuntimeContext, b []byte) []byte { + format := ctx.Option.ColorScheme.Null + b = append(b, format.Header...) + b = append(b, "null"...) + return append(append(b, format.Footer...), ',', '\n') +} + +func appendColon(_ *encoder.RuntimeContext, b []byte) []byte { + return append(b[:len(b)-2], ':', ' ') +} + +func appendMapKeyValue(ctx *encoder.RuntimeContext, code *encoder.Opcode, b, key, value []byte) []byte { + b = appendIndent(ctx, b, code.Indent+1) + b = append(b, key...) + b[len(b)-2] = ':' + b[len(b)-1] = ' ' + return append(b, value...) +} + +func appendMapEnd(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { + b = b[:len(b)-2] + b = append(b, '\n') + b = appendIndent(ctx, b, code.Indent) + return append(b, '}', ',', '\n') +} + +func appendArrayHead(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { + b = append(b, '[', '\n') + return appendIndent(ctx, b, code.Indent+1) +} + +func appendArrayEnd(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { + b = b[:len(b)-2] + b = append(b, '\n') + b = appendIndent(ctx, b, code.Indent) + return append(b, ']', ',', '\n') +} + +func appendEmptyArray(_ *encoder.RuntimeContext, b []byte) []byte { + return append(b, '[', ']', ',', '\n') +} + +func appendEmptyObject(_ *encoder.RuntimeContext, b []byte) []byte { + return append(b, '{', '}', ',', '\n') +} + +func appendObjectEnd(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { + last := len(b) - 1 + // replace comma to newline + b[last-1] = '\n' + b = appendIndent(ctx, b[:last], code.Indent) + return append(b, '}', ',', '\n') +} + +func appendMarshalJSON(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte, v interface{}) ([]byte, error) { + return encoder.AppendMarshalJSONIndent(ctx, code, b, v) +} + +func appendMarshalText(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte, v interface{}) ([]byte, error) { + format := ctx.Option.ColorScheme.String + b = append(b, format.Header...) + bb, err := encoder.AppendMarshalTextIndent(ctx, code, b, v) + if err != nil { + return nil, err + } + return append(bb, format.Footer...), nil +} + +func appendStructHead(_ *encoder.RuntimeContext, b []byte) []byte { + return append(b, '{', '\n') +} + +func appendStructKey(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { + b = appendIndent(ctx, b, code.Indent) + + format := ctx.Option.ColorScheme.ObjectKey + b = append(b, format.Header...) + b = append(b, code.Key[:len(code.Key)-1]...) + b = append(b, format.Footer...) + + return append(b, ':', ' ') +} + +func appendStructEndSkipLast(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { + last := len(b) - 1 + if b[last-1] == '{' { + b[last] = '}' + } else { + if b[last] == '\n' { + // to remove ',' and '\n' characters + b = b[:len(b)-2] + } + b = append(b, '\n') + b = appendIndent(ctx, b, code.Indent-1) + b = append(b, '}') + } + return appendComma(ctx, b) +} + +func restoreIndent(ctx *encoder.RuntimeContext, code *encoder.Opcode, ctxptr uintptr) { + ctx.BaseIndent = uint32(load(ctxptr, code.Length)) +} + +func storeIndent(ctxptr uintptr, code *encoder.Opcode, indent uintptr) { + store(ctxptr, code.Length, indent) +} + +func appendArrayElemIndent(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { + return appendIndent(ctx, b, code.Indent+1) +} + +func appendMapKeyIndent(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { + return appendIndent(ctx, b, code.Indent) +} diff --git a/vendor/github.com/goccy/go-json/internal/encoder/vm_color_indent/vm.go b/vendor/github.com/goccy/go-json/internal/encoder/vm_color_indent/vm.go new file mode 100644 index 000000000..3b4e22e5d --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/encoder/vm_color_indent/vm.go @@ -0,0 +1,4859 @@ +// Code generated by internal/cmd/generator. DO NOT EDIT! +package vm_color_indent + +import ( + "math" + "reflect" + "sort" + "unsafe" + + "github.com/goccy/go-json/internal/encoder" + "github.com/goccy/go-json/internal/runtime" +) + +func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) { + recursiveLevel := 0 + ptrOffset := uintptr(0) + ctxptr := ctx.Ptr() + var code *encoder.Opcode + if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 { + code = codeSet.EscapeKeyCode + } else { + code = codeSet.NoescapeKeyCode + } + + for { + switch code.Op { + default: + return nil, errUnimplementedOp(code.Op) + case encoder.OpPtr: + p := load(ctxptr, code.Idx) + code = code.Next + store(ctxptr, code.Idx, ptrToPtr(p)) + case encoder.OpIntPtr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpInt: + b = appendInt(ctx, b, load(ctxptr, code.Idx), code) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpUintPtr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpUint: + b = appendUint(ctx, b, load(ctxptr, code.Idx), code) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpIntString: + b = append(b, '"') + b = appendInt(ctx, b, load(ctxptr, code.Idx), code) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpUintString: + b = append(b, '"') + b = appendUint(ctx, b, load(ctxptr, code.Idx), code) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpFloat32Ptr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + b = appendComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpFloat32: + b = appendFloat32(ctx, b, ptrToFloat32(load(ctxptr, code.Idx))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpFloat64Ptr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpFloat64: + v := ptrToFloat64(load(ctxptr, code.Idx)) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStringPtr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpString: + b = appendString(ctx, b, ptrToString(load(ctxptr, code.Idx))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpBoolPtr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpBool: + b = appendBool(ctx, b, ptrToBool(load(ctxptr, code.Idx))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpBytesPtr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpBytes: + b = appendByteSlice(ctx, b, ptrToBytes(load(ctxptr, code.Idx))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpNumberPtr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpNumber: + bb, err := appendNumber(ctx, b, ptrToNumber(load(ctxptr, code.Idx))) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + code = code.Next + case encoder.OpInterfacePtr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpInterface: + p := load(ctxptr, code.Idx) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + if recursiveLevel > encoder.StartDetectingCyclesAfter { + for _, seen := range ctx.SeenPtr { + if p == seen { + return nil, errUnsupportedValue(code, p) + } + } + } + ctx.SeenPtr = append(ctx.SeenPtr, p) + var ( + typ *runtime.Type + ifacePtr unsafe.Pointer + ) + up := ptrToUnsafePtr(p) + if code.Flags&encoder.NonEmptyInterfaceFlags != 0 { + iface := (*nonEmptyInterface)(up) + ifacePtr = iface.ptr + if iface.itab != nil { + typ = iface.itab.typ + } + } else { + iface := (*emptyInterface)(up) + ifacePtr = iface.ptr + typ = iface.typ + } + if ifacePtr == nil { + isDirectedNil := typ != nil && typ.Kind() == reflect.Struct && !runtime.IfaceIndir(typ) + if !isDirectedNil { + b = appendNullComma(ctx, b) + code = code.Next + break + } + } + ctx.KeepRefs = append(ctx.KeepRefs, up) + ifaceCodeSet, err := encoder.CompileToGetCodeSet(ctx, uintptr(unsafe.Pointer(typ))) + if err != nil { + return nil, err + } + + totalLength := uintptr(code.Length) + 3 + nextTotalLength := uintptr(ifaceCodeSet.CodeLength) + 3 + + var c *encoder.Opcode + if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 { + c = ifaceCodeSet.InterfaceEscapeKeyCode + } else { + c = ifaceCodeSet.InterfaceNoescapeKeyCode + } + curlen := uintptr(len(ctx.Ptrs)) + offsetNum := ptrOffset / uintptrSize + oldOffset := ptrOffset + ptrOffset += totalLength * uintptrSize + oldBaseIndent := ctx.BaseIndent + ctx.BaseIndent += code.Indent + + newLen := offsetNum + totalLength + nextTotalLength + if curlen < newLen { + ctx.Ptrs = append(ctx.Ptrs, make([]uintptr, newLen-curlen)...) + } + ctxptr = ctx.Ptr() + ptrOffset // assign new ctxptr + + end := ifaceCodeSet.EndCode + store(ctxptr, c.Idx, uintptr(ifacePtr)) + store(ctxptr, end.Idx, oldOffset) + store(ctxptr, end.ElemIdx, uintptr(unsafe.Pointer(code.Next))) + storeIndent(ctxptr, end, uintptr(oldBaseIndent)) + code = c + recursiveLevel++ + case encoder.OpInterfaceEnd: + recursiveLevel-- + + // restore ctxptr + offset := load(ctxptr, code.Idx) + restoreIndent(ctx, code, ctxptr) + ctx.SeenPtr = ctx.SeenPtr[:len(ctx.SeenPtr)-1] + + codePtr := load(ctxptr, code.ElemIdx) + code = (*encoder.Opcode)(ptrToUnsafePtr(codePtr)) + ctxptr = ctx.Ptr() + offset + ptrOffset = offset + case encoder.OpMarshalJSONPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, ptrToPtr(p)) + fallthrough + case encoder.OpMarshalJSON: + p := load(ctxptr, code.Idx) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + if (code.Flags&encoder.IsNilableTypeFlags) != 0 && (code.Flags&encoder.IndirectFlags) != 0 { + p = ptrToPtr(p) + } + bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + code = code.Next + case encoder.OpMarshalTextPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, ptrToPtr(p)) + fallthrough + case encoder.OpMarshalText: + p := load(ctxptr, code.Idx) + if p == 0 { + b = append(b, `""`...) + b = appendComma(ctx, b) + code = code.Next + break + } + if (code.Flags&encoder.IsNilableTypeFlags) != 0 && (code.Flags&encoder.IndirectFlags) != 0 { + p = ptrToPtr(p) + } + bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + code = code.Next + case encoder.OpSlicePtr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.End.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpSlice: + p := load(ctxptr, code.Idx) + slice := ptrToSlice(p) + if p == 0 || slice.Data == nil { + b = appendNullComma(ctx, b) + code = code.End.Next + break + } + store(ctxptr, code.ElemIdx, 0) + store(ctxptr, code.Length, uintptr(slice.Len)) + store(ctxptr, code.Idx, uintptr(slice.Data)) + if slice.Len > 0 { + b = appendArrayHead(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, uintptr(slice.Data)) + } else { + b = appendEmptyArray(ctx, b) + code = code.End.Next + } + case encoder.OpSliceElem: + idx := load(ctxptr, code.ElemIdx) + length := load(ctxptr, code.Length) + idx++ + if idx < length { + b = appendArrayElemIndent(ctx, code, b) + store(ctxptr, code.ElemIdx, idx) + data := load(ctxptr, code.Idx) + size := uintptr(code.Size) + code = code.Next + store(ctxptr, code.Idx, data+idx*size) + } else { + b = appendArrayEnd(ctx, code, b) + code = code.End.Next + } + case encoder.OpArrayPtr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.End.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpArray: + p := load(ctxptr, code.Idx) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.End.Next + break + } + if code.Length > 0 { + b = appendArrayHead(ctx, code, b) + store(ctxptr, code.ElemIdx, 0) + code = code.Next + store(ctxptr, code.Idx, p) + } else { + b = appendEmptyArray(ctx, b) + code = code.End.Next + } + case encoder.OpArrayElem: + idx := load(ctxptr, code.ElemIdx) + idx++ + if idx < uintptr(code.Length) { + b = appendArrayElemIndent(ctx, code, b) + store(ctxptr, code.ElemIdx, idx) + p := load(ctxptr, code.Idx) + size := uintptr(code.Size) + code = code.Next + store(ctxptr, code.Idx, p+idx*size) + } else { + b = appendArrayEnd(ctx, code, b) + code = code.End.Next + } + case encoder.OpMapPtr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.End.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpMap: + p := load(ctxptr, code.Idx) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.End.Next + break + } + uptr := ptrToUnsafePtr(p) + mlen := maplen(uptr) + if mlen <= 0 { + b = appendEmptyObject(ctx, b) + code = code.End.Next + break + } + b = appendStructHead(ctx, b) + unorderedMap := (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 + mapCtx := encoder.NewMapContext(mlen, unorderedMap) + mapiterinit(code.Type, uptr, &mapCtx.Iter) + store(ctxptr, code.Idx, uintptr(unsafe.Pointer(mapCtx))) + ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(mapCtx)) + if unorderedMap { + b = appendMapKeyIndent(ctx, code.Next, b) + } else { + mapCtx.Start = len(b) + mapCtx.First = len(b) + } + key := mapiterkey(&mapCtx.Iter) + store(ctxptr, code.Next.Idx, uintptr(key)) + code = code.Next + case encoder.OpMapKey: + mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.Idx))) + idx := mapCtx.Idx + idx++ + if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 { + if idx < mapCtx.Len { + b = appendMapKeyIndent(ctx, code, b) + mapCtx.Idx = int(idx) + key := mapiterkey(&mapCtx.Iter) + store(ctxptr, code.Next.Idx, uintptr(key)) + code = code.Next + } else { + b = appendObjectEnd(ctx, code, b) + encoder.ReleaseMapContext(mapCtx) + code = code.End.Next + } + } else { + mapCtx.Slice.Items[mapCtx.Idx].Value = b[mapCtx.Start:len(b)] + if idx < mapCtx.Len { + mapCtx.Idx = int(idx) + mapCtx.Start = len(b) + key := mapiterkey(&mapCtx.Iter) + store(ctxptr, code.Next.Idx, uintptr(key)) + code = code.Next + } else { + code = code.End + } + } + case encoder.OpMapValue: + mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.Idx))) + if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 { + b = appendColon(ctx, b) + } else { + mapCtx.Slice.Items[mapCtx.Idx].Key = b[mapCtx.Start:len(b)] + mapCtx.Start = len(b) + } + value := mapitervalue(&mapCtx.Iter) + store(ctxptr, code.Next.Idx, uintptr(value)) + mapiternext(&mapCtx.Iter) + code = code.Next + case encoder.OpMapEnd: + // this operation only used by sorted map. + mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.Idx))) + sort.Sort(mapCtx.Slice) + buf := mapCtx.Buf + for _, item := range mapCtx.Slice.Items { + buf = appendMapKeyValue(ctx, code, buf, item.Key, item.Value) + } + buf = appendMapEnd(ctx, code, buf) + b = b[:mapCtx.First] + b = append(b, buf...) + mapCtx.Buf = buf + encoder.ReleaseMapContext(mapCtx) + code = code.Next + case encoder.OpRecursivePtr: + p := load(ctxptr, code.Idx) + if p == 0 { + code = code.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpRecursive: + ptr := load(ctxptr, code.Idx) + if ptr != 0 { + if recursiveLevel > encoder.StartDetectingCyclesAfter { + for _, seen := range ctx.SeenPtr { + if ptr == seen { + return nil, errUnsupportedValue(code, ptr) + } + } + } + } + ctx.SeenPtr = append(ctx.SeenPtr, ptr) + c := code.Jmp.Code + curlen := uintptr(len(ctx.Ptrs)) + offsetNum := ptrOffset / uintptrSize + oldOffset := ptrOffset + ptrOffset += code.Jmp.CurLen * uintptrSize + oldBaseIndent := ctx.BaseIndent + indentDiffFromTop := c.Indent - 1 + ctx.BaseIndent += code.Indent - indentDiffFromTop + + newLen := offsetNum + code.Jmp.CurLen + code.Jmp.NextLen + if curlen < newLen { + ctx.Ptrs = append(ctx.Ptrs, make([]uintptr, newLen-curlen)...) + } + ctxptr = ctx.Ptr() + ptrOffset // assign new ctxptr + + store(ctxptr, c.Idx, ptr) + store(ctxptr, c.End.Next.Idx, oldOffset) + store(ctxptr, c.End.Next.ElemIdx, uintptr(unsafe.Pointer(code.Next))) + storeIndent(ctxptr, c.End.Next, uintptr(oldBaseIndent)) + code = c + recursiveLevel++ + case encoder.OpRecursiveEnd: + recursiveLevel-- + + // restore ctxptr + restoreIndent(ctx, code, ctxptr) + offset := load(ctxptr, code.Idx) + ctx.SeenPtr = ctx.SeenPtr[:len(ctx.SeenPtr)-1] + + codePtr := load(ctxptr, code.ElemIdx) + code = (*encoder.Opcode)(ptrToUnsafePtr(codePtr)) + ctxptr = ctx.Ptr() + offset + ptrOffset = offset + case encoder.OpStructPtrHead: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHead: + p := load(ctxptr, code.Idx) + if p == 0 && ((code.Flags&encoder.IndirectFlags) != 0 || code.Next.Op == encoder.OpStructEnd) { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if len(code.Key) > 0 { + if (code.Flags&encoder.IsTaggedKeyFlags) != 0 || code.Flags&encoder.AnonymousKeyFlags == 0 { + b = appendStructKey(ctx, code, b) + } + } + p += uintptr(code.Offset) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructPtrHeadOmitEmpty: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmpty: + p := load(ctxptr, code.Idx) + if p == 0 && ((code.Flags&encoder.IndirectFlags) != 0 || code.Next.Op == encoder.OpStructEnd) { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + p += uintptr(code.Offset) + if p == 0 || (ptrToPtr(p) == 0 && (code.Flags&encoder.IsNextOpPtrTypeFlags) != 0) { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructPtrHeadInt: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadInt: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyInt: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyInt: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadIntString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadIntString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyIntString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyIntString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + p += uintptr(code.Offset) + u64 := ptrToUint64(p, code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendInt(ctx, b, p, code) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadIntPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadIntPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendInt(ctx, b, p, code) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyIntPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyIntPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendInt(ctx, b, p, code) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadIntPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadIntPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendInt(ctx, b, p, code) + b = append(b, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyIntPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyIntPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendInt(ctx, b, p, code) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadUint: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadUint: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyUint: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyUint: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadUintString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadUintString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyUintString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyUintString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadUintPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadUintPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendUint(ctx, b, p, code) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyUintPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyUintPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendUint(ctx, b, p, code) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadUintPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadUintPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendUint(ctx, b, p, code) + b = append(b, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyUintPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyUintPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendUint(ctx, b, p, code) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadFloat32: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadFloat32: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyFloat32: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyFloat32: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToFloat32(p + uintptr(code.Offset)) + if v == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + b = appendFloat32(ctx, b, v) + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadFloat32String: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadFloat32String: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyFloat32String: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyFloat32String: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToFloat32(p + uintptr(code.Offset)) + if v == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat32(ctx, b, v) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadFloat32Ptr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadFloat32Ptr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendFloat32(ctx, b, ptrToFloat32(p)) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyFloat32Ptr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyFloat32Ptr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendFloat32(ctx, b, ptrToFloat32(p)) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadFloat32PtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadFloat32PtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendFloat32(ctx, b, ptrToFloat32(p)) + b = append(b, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyFloat32PtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyFloat32PtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat32(ctx, b, ptrToFloat32(p)) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadFloat64: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadFloat64: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + v := ptrToFloat64(p + uintptr(code.Offset)) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = appendFloat64(ctx, b, v) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyFloat64: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyFloat64: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToFloat64(p + uintptr(code.Offset)) + if v == 0 { + code = code.NextField + } else { + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendStructKey(ctx, code, b) + b = appendFloat64(ctx, b, v) + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadFloat64String: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadFloat64String: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToFloat64(p + uintptr(code.Offset)) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat64(ctx, b, v) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyFloat64String: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyFloat64String: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToFloat64(p + uintptr(code.Offset)) + if v == 0 { + code = code.NextField + } else { + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat64(ctx, b, v) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadFloat64Ptr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadFloat64Ptr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyFloat64Ptr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyFloat64Ptr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadFloat64PtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadFloat64PtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = append(b, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyFloat64PtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyFloat64PtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNull(ctx, b) + b = appendComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, ptrToString(p+uintptr(code.Offset))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToString(p + uintptr(code.Offset)) + if v == "" { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, v) + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadStringString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadStringString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p+uintptr(code.Offset))))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyStringString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyStringString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToString(p + uintptr(code.Offset)) + if v == "" { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, string(appendString(ctx, []byte{}, v))) + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadStringPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadStringPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendString(ctx, b, ptrToString(p)) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyStringPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyStringPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, ptrToString(p)) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadStringPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadStringPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyStringPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyStringPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadBool: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadBool: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyBool: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyBool: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToBool(p + uintptr(code.Offset)) + if v { + b = appendStructKey(ctx, code, b) + b = appendBool(ctx, b, v) + b = appendComma(ctx, b) + code = code.Next + } else { + code = code.NextField + } + case encoder.OpStructPtrHeadBoolString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadBoolString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyBoolString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyBoolString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToBool(p + uintptr(code.Offset)) + if v { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendBool(ctx, b, v) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + } else { + code = code.NextField + } + case encoder.OpStructPtrHeadBoolPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadBoolPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendBool(ctx, b, ptrToBool(p)) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyBoolPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyBoolPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendBool(ctx, b, ptrToBool(p)) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadBoolPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadBoolPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendBool(ctx, b, ptrToBool(p)) + b = append(b, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyBoolPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyBoolPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendBool(ctx, b, ptrToBool(p)) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadBytes: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadBytes: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = appendByteSlice(ctx, b, ptrToBytes(p+uintptr(code.Offset))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyBytes: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyBytes: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToBytes(p + uintptr(code.Offset)) + if len(v) == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + b = appendByteSlice(ctx, b, v) + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadBytesPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadBytesPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendByteSlice(ctx, b, ptrToBytes(p)) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyBytesPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyBytesPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendByteSlice(ctx, b, ptrToBytes(p)) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadNumber: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadNumber: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyNumber: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyNumber: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToNumber(p + uintptr(code.Offset)) + if v == "" { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + bb, err := appendNumber(ctx, b, v) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + code = code.Next + } + case encoder.OpStructPtrHeadNumberString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadNumberString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) + if err != nil { + return nil, err + } + b = append(bb, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyNumberString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyNumberString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToNumber(p + uintptr(code.Offset)) + if v == "" { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + bb, err := appendNumber(ctx, b, v) + if err != nil { + return nil, err + } + b = append(bb, '"') + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadNumberPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadNumberPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyNumberPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyNumberPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + } + code = code.Next + case encoder.OpStructPtrHeadNumberPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadNumberPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = append(bb, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyNumberPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyNumberPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = append(bb, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadArray, encoder.OpStructPtrHeadSlice: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadArray, encoder.OpStructHeadSlice: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + p += uintptr(code.Offset) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructPtrHeadOmitEmptyArray: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyArray: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + p += uintptr(code.Offset) + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructPtrHeadOmitEmptySlice: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptySlice: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + p += uintptr(code.Offset) + slice := ptrToSlice(p) + if slice.Len == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructPtrHeadArrayPtr, encoder.OpStructPtrHeadSlicePtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadArrayPtr, encoder.OpStructHeadSlicePtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNullComma(ctx, b) + code = code.NextField + } else { + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructPtrHeadOmitEmptyArrayPtr, encoder.OpStructPtrHeadOmitEmptySlicePtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyArrayPtr, encoder.OpStructHeadOmitEmptySlicePtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructPtrHeadMap: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadMap: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if p != 0 && (code.Flags&encoder.IndirectFlags) != 0 { + p = ptrToPtr(p + uintptr(code.Offset)) + } + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructPtrHeadOmitEmptyMap: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyMap: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if p != 0 && (code.Flags&encoder.IndirectFlags) != 0 { + p = ptrToPtr(p + uintptr(code.Offset)) + } + if maplen(ptrToUnsafePtr(p)) == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructPtrHeadMapPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadMapPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.NextField + break + } + p = ptrToPtr(p + uintptr(code.Offset)) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.NextField + } else { + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p, code.PtrNum) + } + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructPtrHeadOmitEmptyMapPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyMapPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if p == 0 { + code = code.NextField + break + } + p = ptrToPtr(p + uintptr(code.Offset)) + if p == 0 { + code = code.NextField + } else { + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p, code.PtrNum) + } + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructPtrHeadMarshalJSON: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if (code.Flags & encoder.IndirectFlags) != 0 { + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadMarshalJSON: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + p += uintptr(code.Offset) + if (code.Flags & encoder.IsNilableTypeFlags) != 0 { + if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadMarshalJSON { + p = ptrToPtr(p) + } + } + if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyMarshalJSON: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if (code.Flags & encoder.IndirectFlags) != 0 { + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyMarshalJSON: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + p += uintptr(code.Offset) + if (code.Flags & encoder.IsNilableTypeFlags) != 0 { + if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadOmitEmptyMarshalJSON { + p = ptrToPtr(p) + } + } + iface := ptrToInterface(code, p) + if (code.Flags&encoder.NilCheckFlags) != 0 && encoder.IsNilForMarshaler(iface) { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + bb, err := appendMarshalJSON(ctx, code, b, iface) + if err != nil { + return nil, err + } + b = bb + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadMarshalJSONPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadMarshalJSONPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyMarshalJSONPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyMarshalJSONPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if p == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadMarshalText: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if (code.Flags & encoder.IndirectFlags) != 0 { + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadMarshalText: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + p += uintptr(code.Offset) + if (code.Flags & encoder.IsNilableTypeFlags) != 0 { + if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadMarshalText { + p = ptrToPtr(p) + } + } + if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyMarshalText: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if (code.Flags & encoder.IndirectFlags) != 0 { + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyMarshalText: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + p += uintptr(code.Offset) + if (code.Flags & encoder.IsNilableTypeFlags) != 0 { + if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadOmitEmptyMarshalText { + p = ptrToPtr(p) + } + } + if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadMarshalTextPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadMarshalTextPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyMarshalTextPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyMarshalTextPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if p == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructField: + if code.Flags&encoder.IsTaggedKeyFlags != 0 || code.Flags&encoder.AnonymousKeyFlags == 0 { + b = appendStructKey(ctx, code, b) + } + p := load(ctxptr, code.Idx) + uintptr(code.Offset) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructFieldOmitEmpty: + p := load(ctxptr, code.Idx) + p += uintptr(code.Offset) + if ptrToPtr(p) == 0 && (code.Flags&encoder.IsNextOpPtrTypeFlags) != 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructFieldInt: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyInt: + p := load(ctxptr, code.Idx) + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldIntString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyIntString: + p := load(ctxptr, code.Idx) + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldIntPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendInt(ctx, b, p, code) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyIntPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendInt(ctx, b, p, code) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldIntPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendInt(ctx, b, p, code) + b = append(b, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyIntPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendInt(ctx, b, p, code) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldUint: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyUint: + p := load(ctxptr, code.Idx) + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldUintString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyUintString: + p := load(ctxptr, code.Idx) + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldUintPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendUint(ctx, b, p, code) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyUintPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendUint(ctx, b, p, code) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldUintPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendUint(ctx, b, p, code) + b = append(b, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyUintPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendUint(ctx, b, p, code) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldFloat32: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyFloat32: + p := load(ctxptr, code.Idx) + v := ptrToFloat32(p + uintptr(code.Offset)) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = appendFloat32(ctx, b, v) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldFloat32String: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyFloat32String: + p := load(ctxptr, code.Idx) + v := ptrToFloat32(p + uintptr(code.Offset)) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat32(ctx, b, v) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldFloat32Ptr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendFloat32(ctx, b, ptrToFloat32(p)) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyFloat32Ptr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendFloat32(ctx, b, ptrToFloat32(p)) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldFloat32PtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendFloat32(ctx, b, ptrToFloat32(p)) + b = append(b, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyFloat32PtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat32(ctx, b, ptrToFloat32(p)) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldFloat64: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + v := ptrToFloat64(p + uintptr(code.Offset)) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyFloat64: + p := load(ctxptr, code.Idx) + v := ptrToFloat64(p + uintptr(code.Offset)) + if v != 0 { + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendStructKey(ctx, code, b) + b = appendFloat64(ctx, b, v) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldFloat64String: + p := load(ctxptr, code.Idx) + v := ptrToFloat64(p + uintptr(code.Offset)) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat64(ctx, b, v) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyFloat64String: + p := load(ctxptr, code.Idx) + v := ptrToFloat64(p + uintptr(code.Offset)) + if v != 0 { + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat64(ctx, b, v) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldFloat64Ptr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyFloat64Ptr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldFloat64PtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = append(b, '"') + b = appendFloat64(ctx, b, v) + b = append(b, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyFloat64PtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, ptrToString(p+uintptr(code.Offset))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyString: + p := load(ctxptr, code.Idx) + v := ptrToString(p + uintptr(code.Offset)) + if v != "" { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, v) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldStringString: + p := load(ctxptr, code.Idx) + s := ptrToString(p + uintptr(code.Offset)) + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, string(appendString(ctx, []byte{}, s))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyStringString: + p := load(ctxptr, code.Idx) + v := ptrToString(p + uintptr(code.Offset)) + if v != "" { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, string(appendString(ctx, []byte{}, v))) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldStringPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendString(ctx, b, ptrToString(p)) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyStringPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, ptrToString(p)) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldStringPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyStringPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldBool: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyBool: + p := load(ctxptr, code.Idx) + v := ptrToBool(p + uintptr(code.Offset)) + if v { + b = appendStructKey(ctx, code, b) + b = appendBool(ctx, b, v) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldBoolString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyBoolString: + p := load(ctxptr, code.Idx) + v := ptrToBool(p + uintptr(code.Offset)) + if v { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendBool(ctx, b, v) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldBoolPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendBool(ctx, b, ptrToBool(p)) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyBoolPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendBool(ctx, b, ptrToBool(p)) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldBoolPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendBool(ctx, b, ptrToBool(p)) + b = append(b, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyBoolPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendBool(ctx, b, ptrToBool(p)) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldBytes: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendByteSlice(ctx, b, ptrToBytes(p+uintptr(code.Offset))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyBytes: + p := load(ctxptr, code.Idx) + v := ptrToBytes(p + uintptr(code.Offset)) + if len(v) > 0 { + b = appendStructKey(ctx, code, b) + b = appendByteSlice(ctx, b, v) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldBytesPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendByteSlice(ctx, b, ptrToBytes(p)) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyBytesPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendByteSlice(ctx, b, ptrToBytes(p)) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldNumber: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + code = code.Next + case encoder.OpStructFieldOmitEmptyNumber: + p := load(ctxptr, code.Idx) + v := ptrToNumber(p + uintptr(code.Offset)) + if v != "" { + b = appendStructKey(ctx, code, b) + bb, err := appendNumber(ctx, b, v) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + } + code = code.Next + case encoder.OpStructFieldNumberString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = append(b, '"') + bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) + if err != nil { + return nil, err + } + b = append(bb, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyNumberString: + p := load(ctxptr, code.Idx) + v := ptrToNumber(p + uintptr(code.Offset)) + if v != "" { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + bb, err := appendNumber(ctx, b, v) + if err != nil { + return nil, err + } + b = append(bb, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldNumberPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyNumberPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + } + code = code.Next + case encoder.OpStructFieldNumberPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = append(bb, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyNumberPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = append(bb, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldMarshalJSON: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + p += uintptr(code.Offset) + if (code.Flags & encoder.IsNilableTypeFlags) != 0 { + p = ptrToPtr(p) + } + if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyMarshalJSON: + p := load(ctxptr, code.Idx) + p += uintptr(code.Offset) + if (code.Flags & encoder.IsNilableTypeFlags) != 0 { + p = ptrToPtr(p) + } + if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { + code = code.NextField + break + } + iface := ptrToInterface(code, p) + if (code.Flags&encoder.NilCheckFlags) != 0 && encoder.IsNilForMarshaler(iface) { + code = code.NextField + break + } + b = appendStructKey(ctx, code, b) + bb, err := appendMarshalJSON(ctx, code, b, iface) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + code = code.Next + case encoder.OpStructFieldMarshalJSONPtr: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyMarshalJSONPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + } + code = code.Next + case encoder.OpStructFieldMarshalText: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + p += uintptr(code.Offset) + if (code.Flags & encoder.IsNilableTypeFlags) != 0 { + p = ptrToPtr(p) + } + if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyMarshalText: + p := load(ctxptr, code.Idx) + p += uintptr(code.Offset) + if (code.Flags & encoder.IsNilableTypeFlags) != 0 { + p = ptrToPtr(p) + } + if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { + code = code.NextField + break + } + b = appendStructKey(ctx, code, b) + bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + code = code.Next + case encoder.OpStructFieldMarshalTextPtr: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyMarshalTextPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + } + code = code.Next + case encoder.OpStructFieldArray: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p += uintptr(code.Offset) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructFieldOmitEmptyArray: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p += uintptr(code.Offset) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructFieldArrayPtr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructFieldOmitEmptyArrayPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } else { + code = code.NextField + } + case encoder.OpStructFieldSlice: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p += uintptr(code.Offset) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructFieldOmitEmptySlice: + p := load(ctxptr, code.Idx) + p += uintptr(code.Offset) + slice := ptrToSlice(p) + if slice.Len == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructFieldSlicePtr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructFieldOmitEmptySlicePtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } else { + code = code.NextField + } + case encoder.OpStructFieldMap: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToPtr(p + uintptr(code.Offset)) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructFieldOmitEmptyMap: + p := load(ctxptr, code.Idx) + p = ptrToPtr(p + uintptr(code.Offset)) + if p == 0 || maplen(ptrToUnsafePtr(p)) == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructFieldMapPtr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToPtr(p + uintptr(code.Offset)) + if p != 0 { + p = ptrToNPtr(p, code.PtrNum) + } + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructFieldOmitEmptyMapPtr: + p := load(ctxptr, code.Idx) + p = ptrToPtr(p + uintptr(code.Offset)) + if p != 0 { + p = ptrToNPtr(p, code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } else { + code = code.NextField + } + case encoder.OpStructFieldStruct: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p += uintptr(code.Offset) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructFieldOmitEmptyStruct: + p := load(ctxptr, code.Idx) + p += uintptr(code.Offset) + if ptrToPtr(p) == 0 && (code.Flags&encoder.IsNextOpPtrTypeFlags) != 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructEnd: + b = appendStructEndSkipLast(ctx, code, b) + code = code.Next + case encoder.OpStructEndInt: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyInt: + p := load(ctxptr, code.Idx) + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndIntString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyIntString: + p := load(ctxptr, code.Idx) + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndIntPtr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendInt(ctx, b, p, code) + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyIntPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendInt(ctx, b, p, code) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndIntPtrString: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendInt(ctx, b, p, code) + b = append(b, '"') + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyIntPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendInt(ctx, b, p, code) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndUint: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyUint: + p := load(ctxptr, code.Idx) + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndUintString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyUintString: + p := load(ctxptr, code.Idx) + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndUintPtr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendUint(ctx, b, p, code) + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyUintPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendUint(ctx, b, p, code) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndUintPtrString: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendUint(ctx, b, p, code) + b = append(b, '"') + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyUintPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendUint(ctx, b, p, code) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndFloat32: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyFloat32: + p := load(ctxptr, code.Idx) + v := ptrToFloat32(p + uintptr(code.Offset)) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = appendFloat32(ctx, b, v) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndFloat32String: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyFloat32String: + p := load(ctxptr, code.Idx) + v := ptrToFloat32(p + uintptr(code.Offset)) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat32(ctx, b, v) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndFloat32Ptr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendFloat32(ctx, b, ptrToFloat32(p)) + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyFloat32Ptr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendFloat32(ctx, b, ptrToFloat32(p)) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndFloat32PtrString: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendFloat32(ctx, b, ptrToFloat32(p)) + b = append(b, '"') + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyFloat32PtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat32(ctx, b, ptrToFloat32(p)) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndFloat64: + p := load(ctxptr, code.Idx) + v := ptrToFloat64(p + uintptr(code.Offset)) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendStructKey(ctx, code, b) + b = appendFloat64(ctx, b, v) + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyFloat64: + p := load(ctxptr, code.Idx) + v := ptrToFloat64(p + uintptr(code.Offset)) + if v != 0 { + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendStructKey(ctx, code, b) + b = appendFloat64(ctx, b, v) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndFloat64String: + p := load(ctxptr, code.Idx) + v := ptrToFloat64(p + uintptr(code.Offset)) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat64(ctx, b, v) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyFloat64String: + p := load(ctxptr, code.Idx) + v := ptrToFloat64(p + uintptr(code.Offset)) + if v != 0 { + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat64(ctx, b, v) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndFloat64Ptr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + b = appendStructEnd(ctx, code, b) + code = code.Next + break + } + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyFloat64Ptr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndFloat64PtrString: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = append(b, '"') + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyFloat64PtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = append(b, '"') + b = appendFloat64(ctx, b, v) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, ptrToString(p+uintptr(code.Offset))) + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyString: + p := load(ctxptr, code.Idx) + v := ptrToString(p + uintptr(code.Offset)) + if v != "" { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, v) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndStringString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + s := ptrToString(p + uintptr(code.Offset)) + b = appendString(ctx, b, string(appendString(ctx, []byte{}, s))) + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyStringString: + p := load(ctxptr, code.Idx) + v := ptrToString(p + uintptr(code.Offset)) + if v != "" { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, string(appendString(ctx, []byte{}, v))) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndStringPtr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendString(ctx, b, ptrToString(p)) + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyStringPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, ptrToString(p)) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndStringPtrString: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyStringPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndBool: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyBool: + p := load(ctxptr, code.Idx) + v := ptrToBool(p + uintptr(code.Offset)) + if v { + b = appendStructKey(ctx, code, b) + b = appendBool(ctx, b, v) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndBoolString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyBoolString: + p := load(ctxptr, code.Idx) + v := ptrToBool(p + uintptr(code.Offset)) + if v { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendBool(ctx, b, v) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndBoolPtr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendBool(ctx, b, ptrToBool(p)) + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyBoolPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendBool(ctx, b, ptrToBool(p)) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndBoolPtrString: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendBool(ctx, b, ptrToBool(p)) + b = append(b, '"') + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyBoolPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendBool(ctx, b, ptrToBool(p)) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndBytes: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendByteSlice(ctx, b, ptrToBytes(p+uintptr(code.Offset))) + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyBytes: + p := load(ctxptr, code.Idx) + v := ptrToBytes(p + uintptr(code.Offset)) + if len(v) > 0 { + b = appendStructKey(ctx, code, b) + b = appendByteSlice(ctx, b, v) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndBytesPtr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendByteSlice(ctx, b, ptrToBytes(p)) + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyBytesPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendByteSlice(ctx, b, ptrToBytes(p)) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndNumber: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) + if err != nil { + return nil, err + } + b = appendStructEnd(ctx, code, bb) + code = code.Next + case encoder.OpStructEndOmitEmptyNumber: + p := load(ctxptr, code.Idx) + v := ptrToNumber(p + uintptr(code.Offset)) + if v != "" { + b = appendStructKey(ctx, code, b) + bb, err := appendNumber(ctx, b, v) + if err != nil { + return nil, err + } + b = appendStructEnd(ctx, code, bb) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndNumberString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = append(b, '"') + bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) + if err != nil { + return nil, err + } + b = append(bb, '"') + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyNumberString: + p := load(ctxptr, code.Idx) + v := ptrToNumber(p + uintptr(code.Offset)) + if v != "" { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + bb, err := appendNumber(ctx, b, v) + if err != nil { + return nil, err + } + b = append(bb, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndNumberPtr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyNumberPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = appendStructEnd(ctx, code, bb) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndNumberPtrString: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = append(bb, '"') + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyNumberPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = append(bb, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpEnd: + goto END + } + } +END: + return b, nil +} diff --git a/vendor/github.com/goccy/go-json/internal/encoder/vm_indent/debug_vm.go b/vendor/github.com/goccy/go-json/internal/encoder/vm_indent/debug_vm.go new file mode 100644 index 000000000..99395388c --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/encoder/vm_indent/debug_vm.go @@ -0,0 +1,35 @@ +package vm_indent + +import ( + "fmt" + + "github.com/goccy/go-json/internal/encoder" +) + +func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) { + var code *encoder.Opcode + if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 { + code = codeSet.EscapeKeyCode + } else { + code = codeSet.NoescapeKeyCode + } + + defer func() { + if err := recover(); err != nil { + w := ctx.Option.DebugOut + fmt.Fprintln(w, "=============[DEBUG]===============") + fmt.Fprintln(w, "* [TYPE]") + fmt.Fprintln(w, codeSet.Type) + fmt.Fprintf(w, "\n") + fmt.Fprintln(w, "* [ALL OPCODE]") + fmt.Fprintln(w, code.Dump()) + fmt.Fprintf(w, "\n") + fmt.Fprintln(w, "* [CONTEXT]") + fmt.Fprintf(w, "%+v\n", ctx) + fmt.Fprintln(w, "===================================") + panic(err) + } + }() + + return Run(ctx, b, codeSet) +} diff --git a/vendor/github.com/goccy/go-json/internal/encoder/vm_indent/hack.go b/vendor/github.com/goccy/go-json/internal/encoder/vm_indent/hack.go new file mode 100644 index 000000000..9e245bfe5 --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/encoder/vm_indent/hack.go @@ -0,0 +1,9 @@ +package vm_indent + +import ( + // HACK: compile order + // `vm`, `vm_indent`, `vm_color`, `vm_color_indent` packages uses a lot of memory to compile, + // so forcibly make dependencies and avoid compiling in concurrent. + // dependency order: vm => vm_indent => vm_color => vm_color_indent + _ "github.com/goccy/go-json/internal/encoder/vm_color" +) diff --git a/vendor/github.com/goccy/go-json/internal/encoder/vm_indent/util.go b/vendor/github.com/goccy/go-json/internal/encoder/vm_indent/util.go new file mode 100644 index 000000000..6cb745e39 --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/encoder/vm_indent/util.go @@ -0,0 +1,230 @@ +package vm_indent + +import ( + "encoding/json" + "fmt" + "unsafe" + + "github.com/goccy/go-json/internal/encoder" + "github.com/goccy/go-json/internal/runtime" +) + +const uintptrSize = 4 << (^uintptr(0) >> 63) + +var ( + appendInt = encoder.AppendInt + appendUint = encoder.AppendUint + appendFloat32 = encoder.AppendFloat32 + appendFloat64 = encoder.AppendFloat64 + appendString = encoder.AppendString + appendByteSlice = encoder.AppendByteSlice + appendNumber = encoder.AppendNumber + appendStructEnd = encoder.AppendStructEndIndent + appendIndent = encoder.AppendIndent + errUnsupportedValue = encoder.ErrUnsupportedValue + errUnsupportedFloat = encoder.ErrUnsupportedFloat + mapiterinit = encoder.MapIterInit + mapiterkey = encoder.MapIterKey + mapitervalue = encoder.MapIterValue + mapiternext = encoder.MapIterNext + maplen = encoder.MapLen +) + +type emptyInterface struct { + typ *runtime.Type + ptr unsafe.Pointer +} + +type nonEmptyInterface struct { + itab *struct { + ityp *runtime.Type // static interface type + typ *runtime.Type // dynamic concrete type + // unused fields... + } + ptr unsafe.Pointer +} + +func errUnimplementedOp(op encoder.OpType) error { + return fmt.Errorf("encoder (indent): opcode %s has not been implemented", op) +} + +func load(base uintptr, idx uint32) uintptr { + addr := base + uintptr(idx) + return **(**uintptr)(unsafe.Pointer(&addr)) +} + +func store(base uintptr, idx uint32, p uintptr) { + addr := base + uintptr(idx) + **(**uintptr)(unsafe.Pointer(&addr)) = p +} + +func loadNPtr(base uintptr, idx uint32, ptrNum uint8) uintptr { + addr := base + uintptr(idx) + p := **(**uintptr)(unsafe.Pointer(&addr)) + for i := uint8(0); i < ptrNum; i++ { + if p == 0 { + return 0 + } + p = ptrToPtr(p) + } + return p +} + +func ptrToUint64(p uintptr, bitSize uint8) uint64 { + switch bitSize { + case 8: + return (uint64)(**(**uint8)(unsafe.Pointer(&p))) + case 16: + return (uint64)(**(**uint16)(unsafe.Pointer(&p))) + case 32: + return (uint64)(**(**uint32)(unsafe.Pointer(&p))) + case 64: + return **(**uint64)(unsafe.Pointer(&p)) + } + return 0 +} +func ptrToFloat32(p uintptr) float32 { return **(**float32)(unsafe.Pointer(&p)) } +func ptrToFloat64(p uintptr) float64 { return **(**float64)(unsafe.Pointer(&p)) } +func ptrToBool(p uintptr) bool { return **(**bool)(unsafe.Pointer(&p)) } +func ptrToBytes(p uintptr) []byte { return **(**[]byte)(unsafe.Pointer(&p)) } +func ptrToNumber(p uintptr) json.Number { return **(**json.Number)(unsafe.Pointer(&p)) } +func ptrToString(p uintptr) string { return **(**string)(unsafe.Pointer(&p)) } +func ptrToSlice(p uintptr) *runtime.SliceHeader { return *(**runtime.SliceHeader)(unsafe.Pointer(&p)) } +func ptrToPtr(p uintptr) uintptr { + return uintptr(**(**unsafe.Pointer)(unsafe.Pointer(&p))) +} +func ptrToNPtr(p uintptr, ptrNum uint8) uintptr { + for i := uint8(0); i < ptrNum; i++ { + if p == 0 { + return 0 + } + p = ptrToPtr(p) + } + return p +} + +func ptrToUnsafePtr(p uintptr) unsafe.Pointer { + return *(*unsafe.Pointer)(unsafe.Pointer(&p)) +} +func ptrToInterface(code *encoder.Opcode, p uintptr) interface{} { + return *(*interface{})(unsafe.Pointer(&emptyInterface{ + typ: code.Type, + ptr: *(*unsafe.Pointer)(unsafe.Pointer(&p)), + })) +} + +func appendBool(_ *encoder.RuntimeContext, b []byte, v bool) []byte { + if v { + return append(b, "true"...) + } + return append(b, "false"...) +} + +func appendNull(_ *encoder.RuntimeContext, b []byte) []byte { + return append(b, "null"...) +} + +func appendComma(_ *encoder.RuntimeContext, b []byte) []byte { + return append(b, ',', '\n') +} + +func appendNullComma(_ *encoder.RuntimeContext, b []byte) []byte { + return append(b, "null,\n"...) +} + +func appendColon(_ *encoder.RuntimeContext, b []byte) []byte { + return append(b[:len(b)-2], ':', ' ') +} + +func appendMapKeyValue(ctx *encoder.RuntimeContext, code *encoder.Opcode, b, key, value []byte) []byte { + b = appendIndent(ctx, b, code.Indent+1) + b = append(b, key...) + b[len(b)-2] = ':' + b[len(b)-1] = ' ' + return append(b, value...) +} + +func appendMapEnd(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { + b = b[:len(b)-2] + b = append(b, '\n') + b = appendIndent(ctx, b, code.Indent) + return append(b, '}', ',', '\n') +} + +func appendArrayHead(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { + b = append(b, '[', '\n') + return appendIndent(ctx, b, code.Indent+1) +} + +func appendArrayEnd(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { + b = b[:len(b)-2] + b = append(b, '\n') + b = appendIndent(ctx, b, code.Indent) + return append(b, ']', ',', '\n') +} + +func appendEmptyArray(_ *encoder.RuntimeContext, b []byte) []byte { + return append(b, '[', ']', ',', '\n') +} + +func appendEmptyObject(_ *encoder.RuntimeContext, b []byte) []byte { + return append(b, '{', '}', ',', '\n') +} + +func appendObjectEnd(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { + last := len(b) - 1 + // replace comma to newline + b[last-1] = '\n' + b = appendIndent(ctx, b[:last], code.Indent) + return append(b, '}', ',', '\n') +} + +func appendMarshalJSON(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte, v interface{}) ([]byte, error) { + return encoder.AppendMarshalJSONIndent(ctx, code, b, v) +} + +func appendMarshalText(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte, v interface{}) ([]byte, error) { + return encoder.AppendMarshalTextIndent(ctx, code, b, v) +} + +func appendStructHead(_ *encoder.RuntimeContext, b []byte) []byte { + return append(b, '{', '\n') +} + +func appendStructKey(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.Key...) + return append(b, ' ') +} + +func appendStructEndSkipLast(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { + last := len(b) - 1 + if b[last-1] == '{' { + b[last] = '}' + } else { + if b[last] == '\n' { + // to remove ',' and '\n' characters + b = b[:len(b)-2] + } + b = append(b, '\n') + b = appendIndent(ctx, b, code.Indent-1) + b = append(b, '}') + } + return appendComma(ctx, b) +} + +func restoreIndent(ctx *encoder.RuntimeContext, code *encoder.Opcode, ctxptr uintptr) { + ctx.BaseIndent = uint32(load(ctxptr, code.Length)) +} + +func storeIndent(ctxptr uintptr, code *encoder.Opcode, indent uintptr) { + store(ctxptr, code.Length, indent) +} + +func appendArrayElemIndent(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { + return appendIndent(ctx, b, code.Indent+1) +} + +func appendMapKeyIndent(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { + return appendIndent(ctx, b, code.Indent) +} diff --git a/vendor/github.com/goccy/go-json/internal/encoder/vm_indent/vm.go b/vendor/github.com/goccy/go-json/internal/encoder/vm_indent/vm.go new file mode 100644 index 000000000..836c5c8a8 --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/encoder/vm_indent/vm.go @@ -0,0 +1,4859 @@ +// Code generated by internal/cmd/generator. DO NOT EDIT! +package vm_indent + +import ( + "math" + "reflect" + "sort" + "unsafe" + + "github.com/goccy/go-json/internal/encoder" + "github.com/goccy/go-json/internal/runtime" +) + +func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) { + recursiveLevel := 0 + ptrOffset := uintptr(0) + ctxptr := ctx.Ptr() + var code *encoder.Opcode + if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 { + code = codeSet.EscapeKeyCode + } else { + code = codeSet.NoescapeKeyCode + } + + for { + switch code.Op { + default: + return nil, errUnimplementedOp(code.Op) + case encoder.OpPtr: + p := load(ctxptr, code.Idx) + code = code.Next + store(ctxptr, code.Idx, ptrToPtr(p)) + case encoder.OpIntPtr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpInt: + b = appendInt(ctx, b, load(ctxptr, code.Idx), code) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpUintPtr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpUint: + b = appendUint(ctx, b, load(ctxptr, code.Idx), code) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpIntString: + b = append(b, '"') + b = appendInt(ctx, b, load(ctxptr, code.Idx), code) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpUintString: + b = append(b, '"') + b = appendUint(ctx, b, load(ctxptr, code.Idx), code) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpFloat32Ptr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + b = appendComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpFloat32: + b = appendFloat32(ctx, b, ptrToFloat32(load(ctxptr, code.Idx))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpFloat64Ptr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpFloat64: + v := ptrToFloat64(load(ctxptr, code.Idx)) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStringPtr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpString: + b = appendString(ctx, b, ptrToString(load(ctxptr, code.Idx))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpBoolPtr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpBool: + b = appendBool(ctx, b, ptrToBool(load(ctxptr, code.Idx))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpBytesPtr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpBytes: + b = appendByteSlice(ctx, b, ptrToBytes(load(ctxptr, code.Idx))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpNumberPtr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpNumber: + bb, err := appendNumber(ctx, b, ptrToNumber(load(ctxptr, code.Idx))) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + code = code.Next + case encoder.OpInterfacePtr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpInterface: + p := load(ctxptr, code.Idx) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + if recursiveLevel > encoder.StartDetectingCyclesAfter { + for _, seen := range ctx.SeenPtr { + if p == seen { + return nil, errUnsupportedValue(code, p) + } + } + } + ctx.SeenPtr = append(ctx.SeenPtr, p) + var ( + typ *runtime.Type + ifacePtr unsafe.Pointer + ) + up := ptrToUnsafePtr(p) + if code.Flags&encoder.NonEmptyInterfaceFlags != 0 { + iface := (*nonEmptyInterface)(up) + ifacePtr = iface.ptr + if iface.itab != nil { + typ = iface.itab.typ + } + } else { + iface := (*emptyInterface)(up) + ifacePtr = iface.ptr + typ = iface.typ + } + if ifacePtr == nil { + isDirectedNil := typ != nil && typ.Kind() == reflect.Struct && !runtime.IfaceIndir(typ) + if !isDirectedNil { + b = appendNullComma(ctx, b) + code = code.Next + break + } + } + ctx.KeepRefs = append(ctx.KeepRefs, up) + ifaceCodeSet, err := encoder.CompileToGetCodeSet(ctx, uintptr(unsafe.Pointer(typ))) + if err != nil { + return nil, err + } + + totalLength := uintptr(code.Length) + 3 + nextTotalLength := uintptr(ifaceCodeSet.CodeLength) + 3 + + var c *encoder.Opcode + if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 { + c = ifaceCodeSet.InterfaceEscapeKeyCode + } else { + c = ifaceCodeSet.InterfaceNoescapeKeyCode + } + curlen := uintptr(len(ctx.Ptrs)) + offsetNum := ptrOffset / uintptrSize + oldOffset := ptrOffset + ptrOffset += totalLength * uintptrSize + oldBaseIndent := ctx.BaseIndent + ctx.BaseIndent += code.Indent + + newLen := offsetNum + totalLength + nextTotalLength + if curlen < newLen { + ctx.Ptrs = append(ctx.Ptrs, make([]uintptr, newLen-curlen)...) + } + ctxptr = ctx.Ptr() + ptrOffset // assign new ctxptr + + end := ifaceCodeSet.EndCode + store(ctxptr, c.Idx, uintptr(ifacePtr)) + store(ctxptr, end.Idx, oldOffset) + store(ctxptr, end.ElemIdx, uintptr(unsafe.Pointer(code.Next))) + storeIndent(ctxptr, end, uintptr(oldBaseIndent)) + code = c + recursiveLevel++ + case encoder.OpInterfaceEnd: + recursiveLevel-- + + // restore ctxptr + offset := load(ctxptr, code.Idx) + restoreIndent(ctx, code, ctxptr) + ctx.SeenPtr = ctx.SeenPtr[:len(ctx.SeenPtr)-1] + + codePtr := load(ctxptr, code.ElemIdx) + code = (*encoder.Opcode)(ptrToUnsafePtr(codePtr)) + ctxptr = ctx.Ptr() + offset + ptrOffset = offset + case encoder.OpMarshalJSONPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, ptrToPtr(p)) + fallthrough + case encoder.OpMarshalJSON: + p := load(ctxptr, code.Idx) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + if (code.Flags&encoder.IsNilableTypeFlags) != 0 && (code.Flags&encoder.IndirectFlags) != 0 { + p = ptrToPtr(p) + } + bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + code = code.Next + case encoder.OpMarshalTextPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + store(ctxptr, code.Idx, ptrToPtr(p)) + fallthrough + case encoder.OpMarshalText: + p := load(ctxptr, code.Idx) + if p == 0 { + b = append(b, `""`...) + b = appendComma(ctx, b) + code = code.Next + break + } + if (code.Flags&encoder.IsNilableTypeFlags) != 0 && (code.Flags&encoder.IndirectFlags) != 0 { + p = ptrToPtr(p) + } + bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + code = code.Next + case encoder.OpSlicePtr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.End.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpSlice: + p := load(ctxptr, code.Idx) + slice := ptrToSlice(p) + if p == 0 || slice.Data == nil { + b = appendNullComma(ctx, b) + code = code.End.Next + break + } + store(ctxptr, code.ElemIdx, 0) + store(ctxptr, code.Length, uintptr(slice.Len)) + store(ctxptr, code.Idx, uintptr(slice.Data)) + if slice.Len > 0 { + b = appendArrayHead(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, uintptr(slice.Data)) + } else { + b = appendEmptyArray(ctx, b) + code = code.End.Next + } + case encoder.OpSliceElem: + idx := load(ctxptr, code.ElemIdx) + length := load(ctxptr, code.Length) + idx++ + if idx < length { + b = appendArrayElemIndent(ctx, code, b) + store(ctxptr, code.ElemIdx, idx) + data := load(ctxptr, code.Idx) + size := uintptr(code.Size) + code = code.Next + store(ctxptr, code.Idx, data+idx*size) + } else { + b = appendArrayEnd(ctx, code, b) + code = code.End.Next + } + case encoder.OpArrayPtr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.End.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpArray: + p := load(ctxptr, code.Idx) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.End.Next + break + } + if code.Length > 0 { + b = appendArrayHead(ctx, code, b) + store(ctxptr, code.ElemIdx, 0) + code = code.Next + store(ctxptr, code.Idx, p) + } else { + b = appendEmptyArray(ctx, b) + code = code.End.Next + } + case encoder.OpArrayElem: + idx := load(ctxptr, code.ElemIdx) + idx++ + if idx < uintptr(code.Length) { + b = appendArrayElemIndent(ctx, code, b) + store(ctxptr, code.ElemIdx, idx) + p := load(ctxptr, code.Idx) + size := uintptr(code.Size) + code = code.Next + store(ctxptr, code.Idx, p+idx*size) + } else { + b = appendArrayEnd(ctx, code, b) + code = code.End.Next + } + case encoder.OpMapPtr: + p := loadNPtr(ctxptr, code.Idx, code.PtrNum) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.End.Next + break + } + store(ctxptr, code.Idx, p) + fallthrough + case encoder.OpMap: + p := load(ctxptr, code.Idx) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.End.Next + break + } + uptr := ptrToUnsafePtr(p) + mlen := maplen(uptr) + if mlen <= 0 { + b = appendEmptyObject(ctx, b) + code = code.End.Next + break + } + b = appendStructHead(ctx, b) + unorderedMap := (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 + mapCtx := encoder.NewMapContext(mlen, unorderedMap) + mapiterinit(code.Type, uptr, &mapCtx.Iter) + store(ctxptr, code.Idx, uintptr(unsafe.Pointer(mapCtx))) + ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(mapCtx)) + if unorderedMap { + b = appendMapKeyIndent(ctx, code.Next, b) + } else { + mapCtx.Start = len(b) + mapCtx.First = len(b) + } + key := mapiterkey(&mapCtx.Iter) + store(ctxptr, code.Next.Idx, uintptr(key)) + code = code.Next + case encoder.OpMapKey: + mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.Idx))) + idx := mapCtx.Idx + idx++ + if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 { + if idx < mapCtx.Len { + b = appendMapKeyIndent(ctx, code, b) + mapCtx.Idx = int(idx) + key := mapiterkey(&mapCtx.Iter) + store(ctxptr, code.Next.Idx, uintptr(key)) + code = code.Next + } else { + b = appendObjectEnd(ctx, code, b) + encoder.ReleaseMapContext(mapCtx) + code = code.End.Next + } + } else { + mapCtx.Slice.Items[mapCtx.Idx].Value = b[mapCtx.Start:len(b)] + if idx < mapCtx.Len { + mapCtx.Idx = int(idx) + mapCtx.Start = len(b) + key := mapiterkey(&mapCtx.Iter) + store(ctxptr, code.Next.Idx, uintptr(key)) + code = code.Next + } else { + code = code.End + } + } + case encoder.OpMapValue: + mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.Idx))) + if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 { + b = appendColon(ctx, b) + } else { + mapCtx.Slice.Items[mapCtx.Idx].Key = b[mapCtx.Start:len(b)] + mapCtx.Start = len(b) + } + value := mapitervalue(&mapCtx.Iter) + store(ctxptr, code.Next.Idx, uintptr(value)) + mapiternext(&mapCtx.Iter) + code = code.Next + case encoder.OpMapEnd: + // this operation only used by sorted map. + mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.Idx))) + sort.Sort(mapCtx.Slice) + buf := mapCtx.Buf + for _, item := range mapCtx.Slice.Items { + buf = appendMapKeyValue(ctx, code, buf, item.Key, item.Value) + } + buf = appendMapEnd(ctx, code, buf) + b = b[:mapCtx.First] + b = append(b, buf...) + mapCtx.Buf = buf + encoder.ReleaseMapContext(mapCtx) + code = code.Next + case encoder.OpRecursivePtr: + p := load(ctxptr, code.Idx) + if p == 0 { + code = code.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpRecursive: + ptr := load(ctxptr, code.Idx) + if ptr != 0 { + if recursiveLevel > encoder.StartDetectingCyclesAfter { + for _, seen := range ctx.SeenPtr { + if ptr == seen { + return nil, errUnsupportedValue(code, ptr) + } + } + } + } + ctx.SeenPtr = append(ctx.SeenPtr, ptr) + c := code.Jmp.Code + curlen := uintptr(len(ctx.Ptrs)) + offsetNum := ptrOffset / uintptrSize + oldOffset := ptrOffset + ptrOffset += code.Jmp.CurLen * uintptrSize + oldBaseIndent := ctx.BaseIndent + indentDiffFromTop := c.Indent - 1 + ctx.BaseIndent += code.Indent - indentDiffFromTop + + newLen := offsetNum + code.Jmp.CurLen + code.Jmp.NextLen + if curlen < newLen { + ctx.Ptrs = append(ctx.Ptrs, make([]uintptr, newLen-curlen)...) + } + ctxptr = ctx.Ptr() + ptrOffset // assign new ctxptr + + store(ctxptr, c.Idx, ptr) + store(ctxptr, c.End.Next.Idx, oldOffset) + store(ctxptr, c.End.Next.ElemIdx, uintptr(unsafe.Pointer(code.Next))) + storeIndent(ctxptr, c.End.Next, uintptr(oldBaseIndent)) + code = c + recursiveLevel++ + case encoder.OpRecursiveEnd: + recursiveLevel-- + + // restore ctxptr + restoreIndent(ctx, code, ctxptr) + offset := load(ctxptr, code.Idx) + ctx.SeenPtr = ctx.SeenPtr[:len(ctx.SeenPtr)-1] + + codePtr := load(ctxptr, code.ElemIdx) + code = (*encoder.Opcode)(ptrToUnsafePtr(codePtr)) + ctxptr = ctx.Ptr() + offset + ptrOffset = offset + case encoder.OpStructPtrHead: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHead: + p := load(ctxptr, code.Idx) + if p == 0 && ((code.Flags&encoder.IndirectFlags) != 0 || code.Next.Op == encoder.OpStructEnd) { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if len(code.Key) > 0 { + if (code.Flags&encoder.IsTaggedKeyFlags) != 0 || code.Flags&encoder.AnonymousKeyFlags == 0 { + b = appendStructKey(ctx, code, b) + } + } + p += uintptr(code.Offset) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructPtrHeadOmitEmpty: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmpty: + p := load(ctxptr, code.Idx) + if p == 0 && ((code.Flags&encoder.IndirectFlags) != 0 || code.Next.Op == encoder.OpStructEnd) { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + p += uintptr(code.Offset) + if p == 0 || (ptrToPtr(p) == 0 && (code.Flags&encoder.IsNextOpPtrTypeFlags) != 0) { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructPtrHeadInt: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadInt: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyInt: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyInt: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadIntString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadIntString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyIntString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyIntString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + p += uintptr(code.Offset) + u64 := ptrToUint64(p, code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendInt(ctx, b, p, code) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadIntPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadIntPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendInt(ctx, b, p, code) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyIntPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyIntPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendInt(ctx, b, p, code) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadIntPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadIntPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendInt(ctx, b, p, code) + b = append(b, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyIntPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyIntPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendInt(ctx, b, p, code) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadUint: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadUint: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyUint: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyUint: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadUintString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadUintString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyUintString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyUintString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadUintPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadUintPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendUint(ctx, b, p, code) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyUintPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyUintPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendUint(ctx, b, p, code) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadUintPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadUintPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendUint(ctx, b, p, code) + b = append(b, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyUintPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyUintPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendUint(ctx, b, p, code) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadFloat32: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadFloat32: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyFloat32: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyFloat32: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToFloat32(p + uintptr(code.Offset)) + if v == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + b = appendFloat32(ctx, b, v) + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadFloat32String: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadFloat32String: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyFloat32String: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyFloat32String: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToFloat32(p + uintptr(code.Offset)) + if v == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat32(ctx, b, v) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadFloat32Ptr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadFloat32Ptr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendFloat32(ctx, b, ptrToFloat32(p)) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyFloat32Ptr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyFloat32Ptr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendFloat32(ctx, b, ptrToFloat32(p)) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadFloat32PtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadFloat32PtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendFloat32(ctx, b, ptrToFloat32(p)) + b = append(b, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyFloat32PtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyFloat32PtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat32(ctx, b, ptrToFloat32(p)) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadFloat64: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadFloat64: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + v := ptrToFloat64(p + uintptr(code.Offset)) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = appendFloat64(ctx, b, v) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyFloat64: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyFloat64: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToFloat64(p + uintptr(code.Offset)) + if v == 0 { + code = code.NextField + } else { + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendStructKey(ctx, code, b) + b = appendFloat64(ctx, b, v) + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadFloat64String: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadFloat64String: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToFloat64(p + uintptr(code.Offset)) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat64(ctx, b, v) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyFloat64String: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyFloat64String: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToFloat64(p + uintptr(code.Offset)) + if v == 0 { + code = code.NextField + } else { + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat64(ctx, b, v) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadFloat64Ptr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadFloat64Ptr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyFloat64Ptr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyFloat64Ptr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadFloat64PtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadFloat64PtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = append(b, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyFloat64PtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyFloat64PtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNull(ctx, b) + b = appendComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, ptrToString(p+uintptr(code.Offset))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToString(p + uintptr(code.Offset)) + if v == "" { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, v) + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadStringString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadStringString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p+uintptr(code.Offset))))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyStringString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyStringString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToString(p + uintptr(code.Offset)) + if v == "" { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, string(appendString(ctx, []byte{}, v))) + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadStringPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadStringPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendString(ctx, b, ptrToString(p)) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyStringPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyStringPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, ptrToString(p)) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadStringPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadStringPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyStringPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyStringPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadBool: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadBool: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyBool: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyBool: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToBool(p + uintptr(code.Offset)) + if v { + b = appendStructKey(ctx, code, b) + b = appendBool(ctx, b, v) + b = appendComma(ctx, b) + code = code.Next + } else { + code = code.NextField + } + case encoder.OpStructPtrHeadBoolString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadBoolString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyBoolString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyBoolString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToBool(p + uintptr(code.Offset)) + if v { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendBool(ctx, b, v) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + } else { + code = code.NextField + } + case encoder.OpStructPtrHeadBoolPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadBoolPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendBool(ctx, b, ptrToBool(p)) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyBoolPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyBoolPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendBool(ctx, b, ptrToBool(p)) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadBoolPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadBoolPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendBool(ctx, b, ptrToBool(p)) + b = append(b, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyBoolPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyBoolPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendBool(ctx, b, ptrToBool(p)) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadBytes: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadBytes: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = appendByteSlice(ctx, b, ptrToBytes(p+uintptr(code.Offset))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyBytes: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyBytes: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToBytes(p + uintptr(code.Offset)) + if len(v) == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + b = appendByteSlice(ctx, b, v) + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadBytesPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadBytesPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendByteSlice(ctx, b, ptrToBytes(p)) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyBytesPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyBytesPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendByteSlice(ctx, b, ptrToBytes(p)) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadNumber: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadNumber: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyNumber: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyNumber: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToNumber(p + uintptr(code.Offset)) + if v == "" { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + bb, err := appendNumber(ctx, b, v) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + code = code.Next + } + case encoder.OpStructPtrHeadNumberString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadNumberString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) + if err != nil { + return nil, err + } + b = append(bb, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyNumberString: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyNumberString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + v := ptrToNumber(p + uintptr(code.Offset)) + if v == "" { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + bb, err := appendNumber(ctx, b, v) + if err != nil { + return nil, err + } + b = append(bb, '"') + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadNumberPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadNumberPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyNumberPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyNumberPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + } + code = code.Next + case encoder.OpStructPtrHeadNumberPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadNumberPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = append(bb, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyNumberPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyNumberPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = append(bb, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructPtrHeadArray, encoder.OpStructPtrHeadSlice: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadArray, encoder.OpStructHeadSlice: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + p += uintptr(code.Offset) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructPtrHeadOmitEmptyArray: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyArray: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + p += uintptr(code.Offset) + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructPtrHeadOmitEmptySlice: + if (code.Flags & encoder.IndirectFlags) != 0 { + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptySlice: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + p += uintptr(code.Offset) + slice := ptrToSlice(p) + if slice.Len == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructPtrHeadArrayPtr, encoder.OpStructPtrHeadSlicePtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadArrayPtr, encoder.OpStructHeadSlicePtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNullComma(ctx, b) + code = code.NextField + } else { + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructPtrHeadOmitEmptyArrayPtr, encoder.OpStructPtrHeadOmitEmptySlicePtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyArrayPtr, encoder.OpStructHeadOmitEmptySlicePtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructPtrHeadMap: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadMap: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if p != 0 && (code.Flags&encoder.IndirectFlags) != 0 { + p = ptrToPtr(p + uintptr(code.Offset)) + } + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructPtrHeadOmitEmptyMap: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyMap: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if p != 0 && (code.Flags&encoder.IndirectFlags) != 0 { + p = ptrToPtr(p + uintptr(code.Offset)) + } + if maplen(ptrToUnsafePtr(p)) == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructPtrHeadMapPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadMapPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.NextField + break + } + p = ptrToPtr(p + uintptr(code.Offset)) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.NextField + } else { + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p, code.PtrNum) + } + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructPtrHeadOmitEmptyMapPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyMapPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if p == 0 { + code = code.NextField + break + } + p = ptrToPtr(p + uintptr(code.Offset)) + if p == 0 { + code = code.NextField + } else { + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p, code.PtrNum) + } + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructPtrHeadMarshalJSON: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if (code.Flags & encoder.IndirectFlags) != 0 { + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadMarshalJSON: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + p += uintptr(code.Offset) + if (code.Flags & encoder.IsNilableTypeFlags) != 0 { + if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadMarshalJSON { + p = ptrToPtr(p) + } + } + if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyMarshalJSON: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if (code.Flags & encoder.IndirectFlags) != 0 { + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyMarshalJSON: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + p += uintptr(code.Offset) + if (code.Flags & encoder.IsNilableTypeFlags) != 0 { + if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadOmitEmptyMarshalJSON { + p = ptrToPtr(p) + } + } + iface := ptrToInterface(code, p) + if (code.Flags&encoder.NilCheckFlags) != 0 && encoder.IsNilForMarshaler(iface) { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + bb, err := appendMarshalJSON(ctx, code, b, iface) + if err != nil { + return nil, err + } + b = bb + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadMarshalJSONPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadMarshalJSONPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyMarshalJSONPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyMarshalJSONPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if p == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadMarshalText: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if (code.Flags & encoder.IndirectFlags) != 0 { + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadMarshalText: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + p += uintptr(code.Offset) + if (code.Flags & encoder.IsNilableTypeFlags) != 0 { + if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadMarshalText { + p = ptrToPtr(p) + } + } + if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyMarshalText: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if (code.Flags & encoder.IndirectFlags) != 0 { + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyMarshalText: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + p += uintptr(code.Offset) + if (code.Flags & encoder.IsNilableTypeFlags) != 0 { + if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadOmitEmptyMarshalText { + p = ptrToPtr(p) + } + } + if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructPtrHeadMarshalTextPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadMarshalTextPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + b = appendStructKey(ctx, code, b) + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if p == 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructPtrHeadOmitEmptyMarshalTextPtr: + p := load(ctxptr, code.Idx) + if p == 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyMarshalTextPtr: + p := load(ctxptr, code.Idx) + if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 { + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendNullComma(ctx, b) + } + code = code.End.Next + break + } + if (code.Flags & encoder.IndirectFlags) != 0 { + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + } + if code.Flags&encoder.AnonymousHeadFlags == 0 { + b = appendStructHead(ctx, b) + } + if p == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + b = appendComma(ctx, b) + code = code.Next + } + case encoder.OpStructField: + if code.Flags&encoder.IsTaggedKeyFlags != 0 || code.Flags&encoder.AnonymousKeyFlags == 0 { + b = appendStructKey(ctx, code, b) + } + p := load(ctxptr, code.Idx) + uintptr(code.Offset) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructFieldOmitEmpty: + p := load(ctxptr, code.Idx) + p += uintptr(code.Offset) + if ptrToPtr(p) == 0 && (code.Flags&encoder.IsNextOpPtrTypeFlags) != 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructFieldInt: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyInt: + p := load(ctxptr, code.Idx) + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldIntString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyIntString: + p := load(ctxptr, code.Idx) + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldIntPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendInt(ctx, b, p, code) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyIntPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendInt(ctx, b, p, code) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldIntPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendInt(ctx, b, p, code) + b = append(b, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyIntPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendInt(ctx, b, p, code) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldUint: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyUint: + p := load(ctxptr, code.Idx) + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldUintString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyUintString: + p := load(ctxptr, code.Idx) + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldUintPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendUint(ctx, b, p, code) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyUintPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendUint(ctx, b, p, code) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldUintPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendUint(ctx, b, p, code) + b = append(b, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyUintPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendUint(ctx, b, p, code) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldFloat32: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyFloat32: + p := load(ctxptr, code.Idx) + v := ptrToFloat32(p + uintptr(code.Offset)) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = appendFloat32(ctx, b, v) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldFloat32String: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyFloat32String: + p := load(ctxptr, code.Idx) + v := ptrToFloat32(p + uintptr(code.Offset)) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat32(ctx, b, v) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldFloat32Ptr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendFloat32(ctx, b, ptrToFloat32(p)) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyFloat32Ptr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendFloat32(ctx, b, ptrToFloat32(p)) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldFloat32PtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendFloat32(ctx, b, ptrToFloat32(p)) + b = append(b, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyFloat32PtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat32(ctx, b, ptrToFloat32(p)) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldFloat64: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + v := ptrToFloat64(p + uintptr(code.Offset)) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyFloat64: + p := load(ctxptr, code.Idx) + v := ptrToFloat64(p + uintptr(code.Offset)) + if v != 0 { + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendStructKey(ctx, code, b) + b = appendFloat64(ctx, b, v) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldFloat64String: + p := load(ctxptr, code.Idx) + v := ptrToFloat64(p + uintptr(code.Offset)) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat64(ctx, b, v) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyFloat64String: + p := load(ctxptr, code.Idx) + v := ptrToFloat64(p + uintptr(code.Offset)) + if v != 0 { + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat64(ctx, b, v) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldFloat64Ptr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNullComma(ctx, b) + code = code.Next + break + } + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyFloat64Ptr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldFloat64PtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = append(b, '"') + b = appendFloat64(ctx, b, v) + b = append(b, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyFloat64PtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, ptrToString(p+uintptr(code.Offset))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyString: + p := load(ctxptr, code.Idx) + v := ptrToString(p + uintptr(code.Offset)) + if v != "" { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, v) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldStringString: + p := load(ctxptr, code.Idx) + s := ptrToString(p + uintptr(code.Offset)) + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, string(appendString(ctx, []byte{}, s))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyStringString: + p := load(ctxptr, code.Idx) + v := ptrToString(p + uintptr(code.Offset)) + if v != "" { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, string(appendString(ctx, []byte{}, v))) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldStringPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendString(ctx, b, ptrToString(p)) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyStringPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, ptrToString(p)) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldStringPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyStringPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldBool: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyBool: + p := load(ctxptr, code.Idx) + v := ptrToBool(p + uintptr(code.Offset)) + if v { + b = appendStructKey(ctx, code, b) + b = appendBool(ctx, b, v) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldBoolString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) + b = append(b, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyBoolString: + p := load(ctxptr, code.Idx) + v := ptrToBool(p + uintptr(code.Offset)) + if v { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendBool(ctx, b, v) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldBoolPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendBool(ctx, b, ptrToBool(p)) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyBoolPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendBool(ctx, b, ptrToBool(p)) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldBoolPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendBool(ctx, b, ptrToBool(p)) + b = append(b, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyBoolPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendBool(ctx, b, ptrToBool(p)) + b = append(b, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldBytes: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendByteSlice(ctx, b, ptrToBytes(p+uintptr(code.Offset))) + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyBytes: + p := load(ctxptr, code.Idx) + v := ptrToBytes(p + uintptr(code.Offset)) + if len(v) > 0 { + b = appendStructKey(ctx, code, b) + b = appendByteSlice(ctx, b, v) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldBytesPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendByteSlice(ctx, b, ptrToBytes(p)) + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyBytesPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendByteSlice(ctx, b, ptrToBytes(p)) + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldNumber: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + code = code.Next + case encoder.OpStructFieldOmitEmptyNumber: + p := load(ctxptr, code.Idx) + v := ptrToNumber(p + uintptr(code.Offset)) + if v != "" { + b = appendStructKey(ctx, code, b) + bb, err := appendNumber(ctx, b, v) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + } + code = code.Next + case encoder.OpStructFieldNumberString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = append(b, '"') + bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) + if err != nil { + return nil, err + } + b = append(bb, '"') + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyNumberString: + p := load(ctxptr, code.Idx) + v := ptrToNumber(p + uintptr(code.Offset)) + if v != "" { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + bb, err := appendNumber(ctx, b, v) + if err != nil { + return nil, err + } + b = append(bb, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldNumberPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyNumberPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + } + code = code.Next + case encoder.OpStructFieldNumberPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + b = appendStructKey(ctx, code, b) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = append(bb, '"') + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyNumberPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = append(bb, '"') + b = appendComma(ctx, b) + } + code = code.Next + case encoder.OpStructFieldMarshalJSON: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + p += uintptr(code.Offset) + if (code.Flags & encoder.IsNilableTypeFlags) != 0 { + p = ptrToPtr(p) + } + if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyMarshalJSON: + p := load(ctxptr, code.Idx) + p += uintptr(code.Offset) + if (code.Flags & encoder.IsNilableTypeFlags) != 0 { + p = ptrToPtr(p) + } + if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { + code = code.NextField + break + } + iface := ptrToInterface(code, p) + if (code.Flags&encoder.NilCheckFlags) != 0 && encoder.IsNilForMarshaler(iface) { + code = code.NextField + break + } + b = appendStructKey(ctx, code, b) + bb, err := appendMarshalJSON(ctx, code, b, iface) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + code = code.Next + case encoder.OpStructFieldMarshalJSONPtr: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyMarshalJSONPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + } + code = code.Next + case encoder.OpStructFieldMarshalText: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + p += uintptr(code.Offset) + if (code.Flags & encoder.IsNilableTypeFlags) != 0 { + p = ptrToPtr(p) + } + if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyMarshalText: + p := load(ctxptr, code.Idx) + p += uintptr(code.Offset) + if (code.Flags & encoder.IsNilableTypeFlags) != 0 { + p = ptrToPtr(p) + } + if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 { + code = code.NextField + break + } + b = appendStructKey(ctx, code, b) + bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + code = code.Next + case encoder.OpStructFieldMarshalTextPtr: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendComma(ctx, b) + code = code.Next + case encoder.OpStructFieldOmitEmptyMarshalTextPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p)) + if err != nil { + return nil, err + } + b = appendComma(ctx, bb) + } + code = code.Next + case encoder.OpStructFieldArray: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p += uintptr(code.Offset) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructFieldOmitEmptyArray: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p += uintptr(code.Offset) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructFieldArrayPtr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructFieldOmitEmptyArrayPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } else { + code = code.NextField + } + case encoder.OpStructFieldSlice: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p += uintptr(code.Offset) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructFieldOmitEmptySlice: + p := load(ctxptr, code.Idx) + p += uintptr(code.Offset) + slice := ptrToSlice(p) + if slice.Len == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructFieldSlicePtr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructFieldOmitEmptySlicePtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } else { + code = code.NextField + } + case encoder.OpStructFieldMap: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToPtr(p + uintptr(code.Offset)) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructFieldOmitEmptyMap: + p := load(ctxptr, code.Idx) + p = ptrToPtr(p + uintptr(code.Offset)) + if p == 0 || maplen(ptrToUnsafePtr(p)) == 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructFieldMapPtr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToPtr(p + uintptr(code.Offset)) + if p != 0 { + p = ptrToNPtr(p, code.PtrNum) + } + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructFieldOmitEmptyMapPtr: + p := load(ctxptr, code.Idx) + p = ptrToPtr(p + uintptr(code.Offset)) + if p != 0 { + p = ptrToNPtr(p, code.PtrNum) + } + if p != 0 { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } else { + code = code.NextField + } + case encoder.OpStructFieldStruct: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p += uintptr(code.Offset) + code = code.Next + store(ctxptr, code.Idx, p) + case encoder.OpStructFieldOmitEmptyStruct: + p := load(ctxptr, code.Idx) + p += uintptr(code.Offset) + if ptrToPtr(p) == 0 && (code.Flags&encoder.IsNextOpPtrTypeFlags) != 0 { + code = code.NextField + } else { + b = appendStructKey(ctx, code, b) + code = code.Next + store(ctxptr, code.Idx, p) + } + case encoder.OpStructEnd: + b = appendStructEndSkipLast(ctx, code, b) + code = code.Next + case encoder.OpStructEndInt: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyInt: + p := load(ctxptr, code.Idx) + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndIntString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyIntString: + p := load(ctxptr, code.Idx) + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendInt(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndIntPtr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendInt(ctx, b, p, code) + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyIntPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendInt(ctx, b, p, code) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndIntPtrString: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendInt(ctx, b, p, code) + b = append(b, '"') + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyIntPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendInt(ctx, b, p, code) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndUint: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyUint: + p := load(ctxptr, code.Idx) + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndUintString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyUintString: + p := load(ctxptr, code.Idx) + u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize) + v := u64 & ((1 << code.NumBitSize) - 1) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendUint(ctx, b, p+uintptr(code.Offset), code) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndUintPtr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendUint(ctx, b, p, code) + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyUintPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendUint(ctx, b, p, code) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndUintPtrString: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendUint(ctx, b, p, code) + b = append(b, '"') + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyUintPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendUint(ctx, b, p, code) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndFloat32: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyFloat32: + p := load(ctxptr, code.Idx) + v := ptrToFloat32(p + uintptr(code.Offset)) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = appendFloat32(ctx, b, v) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndFloat32String: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset))) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyFloat32String: + p := load(ctxptr, code.Idx) + v := ptrToFloat32(p + uintptr(code.Offset)) + if v != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat32(ctx, b, v) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndFloat32Ptr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendFloat32(ctx, b, ptrToFloat32(p)) + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyFloat32Ptr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendFloat32(ctx, b, ptrToFloat32(p)) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndFloat32PtrString: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendFloat32(ctx, b, ptrToFloat32(p)) + b = append(b, '"') + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyFloat32PtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat32(ctx, b, ptrToFloat32(p)) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndFloat64: + p := load(ctxptr, code.Idx) + v := ptrToFloat64(p + uintptr(code.Offset)) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendStructKey(ctx, code, b) + b = appendFloat64(ctx, b, v) + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyFloat64: + p := load(ctxptr, code.Idx) + v := ptrToFloat64(p + uintptr(code.Offset)) + if v != 0 { + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendStructKey(ctx, code, b) + b = appendFloat64(ctx, b, v) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndFloat64String: + p := load(ctxptr, code.Idx) + v := ptrToFloat64(p + uintptr(code.Offset)) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat64(ctx, b, v) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyFloat64String: + p := load(ctxptr, code.Idx) + v := ptrToFloat64(p + uintptr(code.Offset)) + if v != 0 { + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendFloat64(ctx, b, v) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndFloat64Ptr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + b = appendStructEnd(ctx, code, b) + code = code.Next + break + } + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyFloat64Ptr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndFloat64PtrString: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(ctx, b, v) + b = append(b, '"') + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyFloat64PtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = append(b, '"') + b = appendFloat64(ctx, b, v) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, ptrToString(p+uintptr(code.Offset))) + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyString: + p := load(ctxptr, code.Idx) + v := ptrToString(p + uintptr(code.Offset)) + if v != "" { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, v) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndStringString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + s := ptrToString(p + uintptr(code.Offset)) + b = appendString(ctx, b, string(appendString(ctx, []byte{}, s))) + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyStringString: + p := load(ctxptr, code.Idx) + v := ptrToString(p + uintptr(code.Offset)) + if v != "" { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, string(appendString(ctx, []byte{}, v))) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndStringPtr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendString(ctx, b, ptrToString(p)) + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyStringPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, ptrToString(p)) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndStringPtrString: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyStringPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p)))) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndBool: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyBool: + p := load(ctxptr, code.Idx) + v := ptrToBool(p + uintptr(code.Offset)) + if v { + b = appendStructKey(ctx, code, b) + b = appendBool(ctx, b, v) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndBoolString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset))) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyBoolString: + p := load(ctxptr, code.Idx) + v := ptrToBool(p + uintptr(code.Offset)) + if v { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendBool(ctx, b, v) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndBoolPtr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendBool(ctx, b, ptrToBool(p)) + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyBoolPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendBool(ctx, b, ptrToBool(p)) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndBoolPtrString: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + b = appendBool(ctx, b, ptrToBool(p)) + b = append(b, '"') + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyBoolPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + b = appendBool(ctx, b, ptrToBool(p)) + b = append(b, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndBytes: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = appendByteSlice(ctx, b, ptrToBytes(p+uintptr(code.Offset))) + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyBytes: + p := load(ctxptr, code.Idx) + v := ptrToBytes(p + uintptr(code.Offset)) + if len(v) > 0 { + b = appendStructKey(ctx, code, b) + b = appendByteSlice(ctx, b, v) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndBytesPtr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = appendByteSlice(ctx, b, ptrToBytes(p)) + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyBytesPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = appendByteSlice(ctx, b, ptrToBytes(p)) + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndNumber: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) + if err != nil { + return nil, err + } + b = appendStructEnd(ctx, code, bb) + code = code.Next + case encoder.OpStructEndOmitEmptyNumber: + p := load(ctxptr, code.Idx) + v := ptrToNumber(p + uintptr(code.Offset)) + if v != "" { + b = appendStructKey(ctx, code, b) + bb, err := appendNumber(ctx, b, v) + if err != nil { + return nil, err + } + b = appendStructEnd(ctx, code, bb) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndNumberString: + p := load(ctxptr, code.Idx) + b = appendStructKey(ctx, code, b) + b = append(b, '"') + bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset))) + if err != nil { + return nil, err + } + b = append(bb, '"') + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyNumberString: + p := load(ctxptr, code.Idx) + v := ptrToNumber(p + uintptr(code.Offset)) + if v != "" { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + bb, err := appendNumber(ctx, b, v) + if err != nil { + return nil, err + } + b = append(bb, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndNumberPtr: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = bb + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyNumberPtr: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = appendStructEnd(ctx, code, bb) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpStructEndNumberPtrString: + b = appendStructKey(ctx, code, b) + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p == 0 { + b = appendNull(ctx, b) + } else { + b = append(b, '"') + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = append(bb, '"') + } + b = appendStructEnd(ctx, code, b) + code = code.Next + case encoder.OpStructEndOmitEmptyNumberPtrString: + p := load(ctxptr, code.Idx) + p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum) + if p != 0 { + b = appendStructKey(ctx, code, b) + b = append(b, '"') + bb, err := appendNumber(ctx, b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = append(bb, '"') + b = appendStructEnd(ctx, code, b) + } else { + b = appendStructEndSkipLast(ctx, code, b) + } + code = code.Next + case encoder.OpEnd: + goto END + } + } +END: + return b, nil +} diff --git a/vendor/github.com/goccy/go-json/internal/errors/error.go b/vendor/github.com/goccy/go-json/internal/errors/error.go new file mode 100644 index 000000000..9207d0ff2 --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/errors/error.go @@ -0,0 +1,183 @@ +package errors + +import ( + "fmt" + "reflect" + "strconv" +) + +type InvalidUTF8Error struct { + S string // the whole string value that caused the error +} + +func (e *InvalidUTF8Error) Error() string { + return fmt.Sprintf("json: invalid UTF-8 in string: %s", strconv.Quote(e.S)) +} + +type InvalidUnmarshalError struct { + Type reflect.Type +} + +func (e *InvalidUnmarshalError) Error() string { + if e.Type == nil { + return "json: Unmarshal(nil)" + } + + if e.Type.Kind() != reflect.Ptr { + return fmt.Sprintf("json: Unmarshal(non-pointer %s)", e.Type) + } + return fmt.Sprintf("json: Unmarshal(nil %s)", e.Type) +} + +// A MarshalerError represents an error from calling a MarshalJSON or MarshalText method. +type MarshalerError struct { + Type reflect.Type + Err error + sourceFunc string +} + +func (e *MarshalerError) Error() string { + srcFunc := e.sourceFunc + if srcFunc == "" { + srcFunc = "MarshalJSON" + } + return fmt.Sprintf("json: error calling %s for type %s: %s", srcFunc, e.Type, e.Err.Error()) +} + +// Unwrap returns the underlying error. +func (e *MarshalerError) Unwrap() error { return e.Err } + +// A SyntaxError is a description of a JSON syntax error. +type SyntaxError struct { + msg string // description of error + Offset int64 // error occurred after reading Offset bytes +} + +func (e *SyntaxError) Error() string { return e.msg } + +// An UnmarshalFieldError describes a JSON object key that +// led to an unexported (and therefore unwritable) struct field. +// +// Deprecated: No longer used; kept for compatibility. +type UnmarshalFieldError struct { + Key string + Type reflect.Type + Field reflect.StructField +} + +func (e *UnmarshalFieldError) Error() string { + return fmt.Sprintf("json: cannot unmarshal object key %s into unexported field %s of type %s", + strconv.Quote(e.Key), e.Field.Name, e.Type.String(), + ) +} + +// An UnmarshalTypeError describes a JSON value that was +// not appropriate for a value of a specific Go type. +type UnmarshalTypeError struct { + Value string // description of JSON value - "bool", "array", "number -5" + Type reflect.Type // type of Go value it could not be assigned to + Offset int64 // error occurred after reading Offset bytes + Struct string // name of the struct type containing the field + Field string // the full path from root node to the field +} + +func (e *UnmarshalTypeError) Error() string { + if e.Struct != "" || e.Field != "" { + return fmt.Sprintf("json: cannot unmarshal %s into Go struct field %s.%s of type %s", + e.Value, e.Struct, e.Field, e.Type, + ) + } + return fmt.Sprintf("json: cannot unmarshal %s into Go value of type %s", e.Value, e.Type) +} + +// An UnsupportedTypeError is returned by Marshal when attempting +// to encode an unsupported value type. +type UnsupportedTypeError struct { + Type reflect.Type +} + +func (e *UnsupportedTypeError) Error() string { + return fmt.Sprintf("json: unsupported type: %s", e.Type) +} + +type UnsupportedValueError struct { + Value reflect.Value + Str string +} + +func (e *UnsupportedValueError) Error() string { + return fmt.Sprintf("json: unsupported value: %s", e.Str) +} + +func ErrSyntax(msg string, offset int64) *SyntaxError { + return &SyntaxError{msg: msg, Offset: offset} +} + +func ErrMarshaler(typ reflect.Type, err error, msg string) *MarshalerError { + return &MarshalerError{ + Type: typ, + Err: err, + sourceFunc: msg, + } +} + +func ErrExceededMaxDepth(c byte, cursor int64) *SyntaxError { + return &SyntaxError{ + msg: fmt.Sprintf(`invalid character "%c" exceeded max depth`, c), + Offset: cursor, + } +} + +func ErrNotAtBeginningOfValue(cursor int64) *SyntaxError { + return &SyntaxError{msg: "not at beginning of value", Offset: cursor} +} + +func ErrUnexpectedEndOfJSON(msg string, cursor int64) *SyntaxError { + return &SyntaxError{ + msg: fmt.Sprintf("json: %s unexpected end of JSON input", msg), + Offset: cursor, + } +} + +func ErrExpected(msg string, cursor int64) *SyntaxError { + return &SyntaxError{msg: fmt.Sprintf("expected %s", msg), Offset: cursor} +} + +func ErrInvalidCharacter(c byte, context string, cursor int64) *SyntaxError { + if c == 0 { + return &SyntaxError{ + msg: fmt.Sprintf("json: invalid character as %s", context), + Offset: cursor, + } + } + return &SyntaxError{ + msg: fmt.Sprintf("json: invalid character %c as %s", c, context), + Offset: cursor, + } +} + +func ErrInvalidBeginningOfValue(c byte, cursor int64) *SyntaxError { + return &SyntaxError{ + msg: fmt.Sprintf("invalid character '%c' looking for beginning of value", c), + Offset: cursor, + } +} + +type PathError struct { + msg string +} + +func (e *PathError) Error() string { + return fmt.Sprintf("json: invalid path format: %s", e.msg) +} + +func ErrInvalidPath(msg string, args ...interface{}) *PathError { + if len(args) != 0 { + return &PathError{msg: fmt.Sprintf(msg, args...)} + } + return &PathError{msg: msg} +} + +func ErrEmptyPath() *PathError { + return &PathError{msg: "path is empty"} +} diff --git a/vendor/github.com/goccy/go-json/internal/runtime/rtype.go b/vendor/github.com/goccy/go-json/internal/runtime/rtype.go new file mode 100644 index 000000000..4db10debe --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/runtime/rtype.go @@ -0,0 +1,263 @@ +package runtime + +import ( + "reflect" + "unsafe" +) + +// Type representing reflect.rtype for noescape trick +type Type struct{} + +//go:linkname rtype_Align reflect.(*rtype).Align +//go:noescape +func rtype_Align(*Type) int + +func (t *Type) Align() int { + return rtype_Align(t) +} + +//go:linkname rtype_FieldAlign reflect.(*rtype).FieldAlign +//go:noescape +func rtype_FieldAlign(*Type) int + +func (t *Type) FieldAlign() int { + return rtype_FieldAlign(t) +} + +//go:linkname rtype_Method reflect.(*rtype).Method +//go:noescape +func rtype_Method(*Type, int) reflect.Method + +func (t *Type) Method(a0 int) reflect.Method { + return rtype_Method(t, a0) +} + +//go:linkname rtype_MethodByName reflect.(*rtype).MethodByName +//go:noescape +func rtype_MethodByName(*Type, string) (reflect.Method, bool) + +func (t *Type) MethodByName(a0 string) (reflect.Method, bool) { + return rtype_MethodByName(t, a0) +} + +//go:linkname rtype_NumMethod reflect.(*rtype).NumMethod +//go:noescape +func rtype_NumMethod(*Type) int + +func (t *Type) NumMethod() int { + return rtype_NumMethod(t) +} + +//go:linkname rtype_Name reflect.(*rtype).Name +//go:noescape +func rtype_Name(*Type) string + +func (t *Type) Name() string { + return rtype_Name(t) +} + +//go:linkname rtype_PkgPath reflect.(*rtype).PkgPath +//go:noescape +func rtype_PkgPath(*Type) string + +func (t *Type) PkgPath() string { + return rtype_PkgPath(t) +} + +//go:linkname rtype_Size reflect.(*rtype).Size +//go:noescape +func rtype_Size(*Type) uintptr + +func (t *Type) Size() uintptr { + return rtype_Size(t) +} + +//go:linkname rtype_String reflect.(*rtype).String +//go:noescape +func rtype_String(*Type) string + +func (t *Type) String() string { + return rtype_String(t) +} + +//go:linkname rtype_Kind reflect.(*rtype).Kind +//go:noescape +func rtype_Kind(*Type) reflect.Kind + +func (t *Type) Kind() reflect.Kind { + return rtype_Kind(t) +} + +//go:linkname rtype_Implements reflect.(*rtype).Implements +//go:noescape +func rtype_Implements(*Type, reflect.Type) bool + +func (t *Type) Implements(u reflect.Type) bool { + return rtype_Implements(t, u) +} + +//go:linkname rtype_AssignableTo reflect.(*rtype).AssignableTo +//go:noescape +func rtype_AssignableTo(*Type, reflect.Type) bool + +func (t *Type) AssignableTo(u reflect.Type) bool { + return rtype_AssignableTo(t, u) +} + +//go:linkname rtype_ConvertibleTo reflect.(*rtype).ConvertibleTo +//go:noescape +func rtype_ConvertibleTo(*Type, reflect.Type) bool + +func (t *Type) ConvertibleTo(u reflect.Type) bool { + return rtype_ConvertibleTo(t, u) +} + +//go:linkname rtype_Comparable reflect.(*rtype).Comparable +//go:noescape +func rtype_Comparable(*Type) bool + +func (t *Type) Comparable() bool { + return rtype_Comparable(t) +} + +//go:linkname rtype_Bits reflect.(*rtype).Bits +//go:noescape +func rtype_Bits(*Type) int + +func (t *Type) Bits() int { + return rtype_Bits(t) +} + +//go:linkname rtype_ChanDir reflect.(*rtype).ChanDir +//go:noescape +func rtype_ChanDir(*Type) reflect.ChanDir + +func (t *Type) ChanDir() reflect.ChanDir { + return rtype_ChanDir(t) +} + +//go:linkname rtype_IsVariadic reflect.(*rtype).IsVariadic +//go:noescape +func rtype_IsVariadic(*Type) bool + +func (t *Type) IsVariadic() bool { + return rtype_IsVariadic(t) +} + +//go:linkname rtype_Elem reflect.(*rtype).Elem +//go:noescape +func rtype_Elem(*Type) reflect.Type + +func (t *Type) Elem() *Type { + return Type2RType(rtype_Elem(t)) +} + +//go:linkname rtype_Field reflect.(*rtype).Field +//go:noescape +func rtype_Field(*Type, int) reflect.StructField + +func (t *Type) Field(i int) reflect.StructField { + return rtype_Field(t, i) +} + +//go:linkname rtype_FieldByIndex reflect.(*rtype).FieldByIndex +//go:noescape +func rtype_FieldByIndex(*Type, []int) reflect.StructField + +func (t *Type) FieldByIndex(index []int) reflect.StructField { + return rtype_FieldByIndex(t, index) +} + +//go:linkname rtype_FieldByName reflect.(*rtype).FieldByName +//go:noescape +func rtype_FieldByName(*Type, string) (reflect.StructField, bool) + +func (t *Type) FieldByName(name string) (reflect.StructField, bool) { + return rtype_FieldByName(t, name) +} + +//go:linkname rtype_FieldByNameFunc reflect.(*rtype).FieldByNameFunc +//go:noescape +func rtype_FieldByNameFunc(*Type, func(string) bool) (reflect.StructField, bool) + +func (t *Type) FieldByNameFunc(match func(string) bool) (reflect.StructField, bool) { + return rtype_FieldByNameFunc(t, match) +} + +//go:linkname rtype_In reflect.(*rtype).In +//go:noescape +func rtype_In(*Type, int) reflect.Type + +func (t *Type) In(i int) reflect.Type { + return rtype_In(t, i) +} + +//go:linkname rtype_Key reflect.(*rtype).Key +//go:noescape +func rtype_Key(*Type) reflect.Type + +func (t *Type) Key() *Type { + return Type2RType(rtype_Key(t)) +} + +//go:linkname rtype_Len reflect.(*rtype).Len +//go:noescape +func rtype_Len(*Type) int + +func (t *Type) Len() int { + return rtype_Len(t) +} + +//go:linkname rtype_NumField reflect.(*rtype).NumField +//go:noescape +func rtype_NumField(*Type) int + +func (t *Type) NumField() int { + return rtype_NumField(t) +} + +//go:linkname rtype_NumIn reflect.(*rtype).NumIn +//go:noescape +func rtype_NumIn(*Type) int + +func (t *Type) NumIn() int { + return rtype_NumIn(t) +} + +//go:linkname rtype_NumOut reflect.(*rtype).NumOut +//go:noescape +func rtype_NumOut(*Type) int + +func (t *Type) NumOut() int { + return rtype_NumOut(t) +} + +//go:linkname rtype_Out reflect.(*rtype).Out +//go:noescape +func rtype_Out(*Type, int) reflect.Type + +//go:linkname PtrTo reflect.(*rtype).ptrTo +//go:noescape +func PtrTo(*Type) *Type + +func (t *Type) Out(i int) reflect.Type { + return rtype_Out(t, i) +} + +//go:linkname IfaceIndir reflect.ifaceIndir +//go:noescape +func IfaceIndir(*Type) bool + +//go:linkname RType2Type reflect.toType +//go:noescape +func RType2Type(t *Type) reflect.Type + +//go:nolint structcheck +type emptyInterface struct { + _ *Type + ptr unsafe.Pointer +} + +func Type2RType(t reflect.Type) *Type { + return (*Type)(((*emptyInterface)(unsafe.Pointer(&t))).ptr) +} diff --git a/vendor/github.com/goccy/go-json/internal/runtime/struct_field.go b/vendor/github.com/goccy/go-json/internal/runtime/struct_field.go new file mode 100644 index 000000000..baab0c597 --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/runtime/struct_field.go @@ -0,0 +1,91 @@ +package runtime + +import ( + "reflect" + "strings" + "unicode" +) + +func getTag(field reflect.StructField) string { + return field.Tag.Get("json") +} + +func IsIgnoredStructField(field reflect.StructField) bool { + if field.PkgPath != "" { + if field.Anonymous { + t := field.Type + if t.Kind() == reflect.Ptr { + t = t.Elem() + } + if t.Kind() != reflect.Struct { + return true + } + } else { + // private field + return true + } + } + tag := getTag(field) + return tag == "-" +} + +type StructTag struct { + Key string + IsTaggedKey bool + IsOmitEmpty bool + IsString bool + Field reflect.StructField +} + +type StructTags []*StructTag + +func (t StructTags) ExistsKey(key string) bool { + for _, tt := range t { + if tt.Key == key { + return true + } + } + return false +} + +func isValidTag(s string) bool { + if s == "" { + return false + } + for _, c := range s { + switch { + case strings.ContainsRune("!#$%&()*+-./:<=>?@[]^_{|}~ ", c): + // Backslash and quote chars are reserved, but + // otherwise any punctuation chars are allowed + // in a tag name. + case !unicode.IsLetter(c) && !unicode.IsDigit(c): + return false + } + } + return true +} + +func StructTagFromField(field reflect.StructField) *StructTag { + keyName := field.Name + tag := getTag(field) + st := &StructTag{Field: field} + opts := strings.Split(tag, ",") + if len(opts) > 0 { + if opts[0] != "" && isValidTag(opts[0]) { + keyName = opts[0] + st.IsTaggedKey = true + } + } + st.Key = keyName + if len(opts) > 1 { + for _, opt := range opts[1:] { + switch opt { + case "omitempty": + st.IsOmitEmpty = true + case "string": + st.IsString = true + } + } + } + return st +} diff --git a/vendor/github.com/goccy/go-json/internal/runtime/type.go b/vendor/github.com/goccy/go-json/internal/runtime/type.go new file mode 100644 index 000000000..0167cd2c0 --- /dev/null +++ b/vendor/github.com/goccy/go-json/internal/runtime/type.go @@ -0,0 +1,100 @@ +package runtime + +import ( + "reflect" + "unsafe" +) + +type SliceHeader struct { + Data unsafe.Pointer + Len int + Cap int +} + +const ( + maxAcceptableTypeAddrRange = 1024 * 1024 * 2 // 2 Mib +) + +type TypeAddr struct { + BaseTypeAddr uintptr + MaxTypeAddr uintptr + AddrRange uintptr + AddrShift uintptr +} + +var ( + typeAddr *TypeAddr + alreadyAnalyzed bool +) + +//go:linkname typelinks reflect.typelinks +func typelinks() ([]unsafe.Pointer, [][]int32) + +//go:linkname rtypeOff reflect.rtypeOff +func rtypeOff(unsafe.Pointer, int32) unsafe.Pointer + +func AnalyzeTypeAddr() *TypeAddr { + defer func() { + alreadyAnalyzed = true + }() + if alreadyAnalyzed { + return typeAddr + } + sections, offsets := typelinks() + if len(sections) != 1 { + return nil + } + if len(offsets) != 1 { + return nil + } + section := sections[0] + offset := offsets[0] + var ( + min uintptr = uintptr(^uint(0)) + max uintptr = 0 + isAligned64 = true + isAligned32 = true + ) + for i := 0; i < len(offset); i++ { + typ := (*Type)(rtypeOff(section, offset[i])) + addr := uintptr(unsafe.Pointer(typ)) + if min > addr { + min = addr + } + if max < addr { + max = addr + } + if typ.Kind() == reflect.Ptr { + addr = uintptr(unsafe.Pointer(typ.Elem())) + if min > addr { + min = addr + } + if max < addr { + max = addr + } + } + isAligned64 = isAligned64 && (addr-min)&63 == 0 + isAligned32 = isAligned32 && (addr-min)&31 == 0 + } + addrRange := max - min + if addrRange == 0 { + return nil + } + var addrShift uintptr + if isAligned64 { + addrShift = 6 + } else if isAligned32 { + addrShift = 5 + } + cacheSize := addrRange >> addrShift + if cacheSize > maxAcceptableTypeAddrRange { + return nil + } + typeAddr = &TypeAddr{ + BaseTypeAddr: min, + MaxTypeAddr: max, + AddrRange: addrRange, + AddrShift: addrShift, + } + return typeAddr +} diff --git a/vendor/github.com/goccy/go-json/json.go b/vendor/github.com/goccy/go-json/json.go new file mode 100644 index 000000000..413cb20bf --- /dev/null +++ b/vendor/github.com/goccy/go-json/json.go @@ -0,0 +1,371 @@ +package json + +import ( + "bytes" + "context" + "encoding/json" + + "github.com/goccy/go-json/internal/encoder" +) + +// Marshaler is the interface implemented by types that +// can marshal themselves into valid JSON. +type Marshaler interface { + MarshalJSON() ([]byte, error) +} + +// MarshalerContext is the interface implemented by types that +// can marshal themselves into valid JSON with context.Context. +type MarshalerContext interface { + MarshalJSON(context.Context) ([]byte, error) +} + +// Unmarshaler is the interface implemented by types +// that can unmarshal a JSON description of themselves. +// The input can be assumed to be a valid encoding of +// a JSON value. UnmarshalJSON must copy the JSON data +// if it wishes to retain the data after returning. +// +// By convention, to approximate the behavior of Unmarshal itself, +// Unmarshalers implement UnmarshalJSON([]byte("null")) as a no-op. +type Unmarshaler interface { + UnmarshalJSON([]byte) error +} + +// UnmarshalerContext is the interface implemented by types +// that can unmarshal with context.Context a JSON description of themselves. +type UnmarshalerContext interface { + UnmarshalJSON(context.Context, []byte) error +} + +// Marshal returns the JSON encoding of v. +// +// Marshal traverses the value v recursively. +// If an encountered value implements the Marshaler interface +// and is not a nil pointer, Marshal calls its MarshalJSON method +// to produce JSON. If no MarshalJSON method is present but the +// value implements encoding.TextMarshaler instead, Marshal calls +// its MarshalText method and encodes the result as a JSON string. +// The nil pointer exception is not strictly necessary +// but mimics a similar, necessary exception in the behavior of +// UnmarshalJSON. +// +// Otherwise, Marshal uses the following type-dependent default encodings: +// +// Boolean values encode as JSON booleans. +// +// Floating point, integer, and Number values encode as JSON numbers. +// +// String values encode as JSON strings coerced to valid UTF-8, +// replacing invalid bytes with the Unicode replacement rune. +// The angle brackets "<" and ">" are escaped to "\u003c" and "\u003e" +// to keep some browsers from misinterpreting JSON output as HTML. +// Ampersand "&" is also escaped to "\u0026" for the same reason. +// This escaping can be disabled using an Encoder that had SetEscapeHTML(false) +// called on it. +// +// Array and slice values encode as JSON arrays, except that +// []byte encodes as a base64-encoded string, and a nil slice +// encodes as the null JSON value. +// +// Struct values encode as JSON objects. +// Each exported struct field becomes a member of the object, using the +// field name as the object key, unless the field is omitted for one of the +// reasons given below. +// +// The encoding of each struct field can be customized by the format string +// stored under the "json" key in the struct field's tag. +// The format string gives the name of the field, possibly followed by a +// comma-separated list of options. The name may be empty in order to +// specify options without overriding the default field name. +// +// The "omitempty" option specifies that the field should be omitted +// from the encoding if the field has an empty value, defined as +// false, 0, a nil pointer, a nil interface value, and any empty array, +// slice, map, or string. +// +// As a special case, if the field tag is "-", the field is always omitted. +// Note that a field with name "-" can still be generated using the tag "-,". +// +// Examples of struct field tags and their meanings: +// +// // Field appears in JSON as key "myName". +// Field int `json:"myName"` +// +// // Field appears in JSON as key "myName" and +// // the field is omitted from the object if its value is empty, +// // as defined above. +// Field int `json:"myName,omitempty"` +// +// // Field appears in JSON as key "Field" (the default), but +// // the field is skipped if empty. +// // Note the leading comma. +// Field int `json:",omitempty"` +// +// // Field is ignored by this package. +// Field int `json:"-"` +// +// // Field appears in JSON as key "-". +// Field int `json:"-,"` +// +// The "string" option signals that a field is stored as JSON inside a +// JSON-encoded string. It applies only to fields of string, floating point, +// integer, or boolean types. This extra level of encoding is sometimes used +// when communicating with JavaScript programs: +// +// Int64String int64 `json:",string"` +// +// The key name will be used if it's a non-empty string consisting of +// only Unicode letters, digits, and ASCII punctuation except quotation +// marks, backslash, and comma. +// +// Anonymous struct fields are usually marshaled as if their inner exported fields +// were fields in the outer struct, subject to the usual Go visibility rules amended +// as described in the next paragraph. +// An anonymous struct field with a name given in its JSON tag is treated as +// having that name, rather than being anonymous. +// An anonymous struct field of interface type is treated the same as having +// that type as its name, rather than being anonymous. +// +// The Go visibility rules for struct fields are amended for JSON when +// deciding which field to marshal or unmarshal. If there are +// multiple fields at the same level, and that level is the least +// nested (and would therefore be the nesting level selected by the +// usual Go rules), the following extra rules apply: +// +// 1) Of those fields, if any are JSON-tagged, only tagged fields are considered, +// even if there are multiple untagged fields that would otherwise conflict. +// +// 2) If there is exactly one field (tagged or not according to the first rule), that is selected. +// +// 3) Otherwise there are multiple fields, and all are ignored; no error occurs. +// +// Handling of anonymous struct fields is new in Go 1.1. +// Prior to Go 1.1, anonymous struct fields were ignored. To force ignoring of +// an anonymous struct field in both current and earlier versions, give the field +// a JSON tag of "-". +// +// Map values encode as JSON objects. The map's key type must either be a +// string, an integer type, or implement encoding.TextMarshaler. The map keys +// are sorted and used as JSON object keys by applying the following rules, +// subject to the UTF-8 coercion described for string values above: +// - string keys are used directly +// - encoding.TextMarshalers are marshaled +// - integer keys are converted to strings +// +// Pointer values encode as the value pointed to. +// A nil pointer encodes as the null JSON value. +// +// Interface values encode as the value contained in the interface. +// A nil interface value encodes as the null JSON value. +// +// Channel, complex, and function values cannot be encoded in JSON. +// Attempting to encode such a value causes Marshal to return +// an UnsupportedTypeError. +// +// JSON cannot represent cyclic data structures and Marshal does not +// handle them. Passing cyclic structures to Marshal will result in +// an infinite recursion. +// +func Marshal(v interface{}) ([]byte, error) { + return MarshalWithOption(v) +} + +// MarshalNoEscape returns the JSON encoding of v and doesn't escape v. +func MarshalNoEscape(v interface{}) ([]byte, error) { + return marshalNoEscape(v) +} + +// MarshalContext returns the JSON encoding of v with context.Context and EncodeOption. +func MarshalContext(ctx context.Context, v interface{}, optFuncs ...EncodeOptionFunc) ([]byte, error) { + return marshalContext(ctx, v, optFuncs...) +} + +// MarshalWithOption returns the JSON encoding of v with EncodeOption. +func MarshalWithOption(v interface{}, optFuncs ...EncodeOptionFunc) ([]byte, error) { + return marshal(v, optFuncs...) +} + +// MarshalIndent is like Marshal but applies Indent to format the output. +// Each JSON element in the output will begin on a new line beginning with prefix +// followed by one or more copies of indent according to the indentation nesting. +func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) { + return MarshalIndentWithOption(v, prefix, indent) +} + +// MarshalIndentWithOption is like Marshal but applies Indent to format the output with EncodeOption. +func MarshalIndentWithOption(v interface{}, prefix, indent string, optFuncs ...EncodeOptionFunc) ([]byte, error) { + return marshalIndent(v, prefix, indent, optFuncs...) +} + +// Unmarshal parses the JSON-encoded data and stores the result +// in the value pointed to by v. If v is nil or not a pointer, +// Unmarshal returns an InvalidUnmarshalError. +// +// Unmarshal uses the inverse of the encodings that +// Marshal uses, allocating maps, slices, and pointers as necessary, +// with the following additional rules: +// +// To unmarshal JSON into a pointer, Unmarshal first handles the case of +// the JSON being the JSON literal null. In that case, Unmarshal sets +// the pointer to nil. Otherwise, Unmarshal unmarshals the JSON into +// the value pointed at by the pointer. If the pointer is nil, Unmarshal +// allocates a new value for it to point to. +// +// To unmarshal JSON into a value implementing the Unmarshaler interface, +// Unmarshal calls that value's UnmarshalJSON method, including +// when the input is a JSON null. +// Otherwise, if the value implements encoding.TextUnmarshaler +// and the input is a JSON quoted string, Unmarshal calls that value's +// UnmarshalText method with the unquoted form of the string. +// +// To unmarshal JSON into a struct, Unmarshal matches incoming object +// keys to the keys used by Marshal (either the struct field name or its tag), +// preferring an exact match but also accepting a case-insensitive match. By +// default, object keys which don't have a corresponding struct field are +// ignored (see Decoder.DisallowUnknownFields for an alternative). +// +// To unmarshal JSON into an interface value, +// Unmarshal stores one of these in the interface value: +// +// bool, for JSON booleans +// float64, for JSON numbers +// string, for JSON strings +// []interface{}, for JSON arrays +// map[string]interface{}, for JSON objects +// nil for JSON null +// +// To unmarshal a JSON array into a slice, Unmarshal resets the slice length +// to zero and then appends each element to the slice. +// As a special case, to unmarshal an empty JSON array into a slice, +// Unmarshal replaces the slice with a new empty slice. +// +// To unmarshal a JSON array into a Go array, Unmarshal decodes +// JSON array elements into corresponding Go array elements. +// If the Go array is smaller than the JSON array, +// the additional JSON array elements are discarded. +// If the JSON array is smaller than the Go array, +// the additional Go array elements are set to zero values. +// +// To unmarshal a JSON object into a map, Unmarshal first establishes a map to +// use. If the map is nil, Unmarshal allocates a new map. Otherwise Unmarshal +// reuses the existing map, keeping existing entries. Unmarshal then stores +// key-value pairs from the JSON object into the map. The map's key type must +// either be any string type, an integer, implement json.Unmarshaler, or +// implement encoding.TextUnmarshaler. +// +// If a JSON value is not appropriate for a given target type, +// or if a JSON number overflows the target type, Unmarshal +// skips that field and completes the unmarshaling as best it can. +// If no more serious errors are encountered, Unmarshal returns +// an UnmarshalTypeError describing the earliest such error. In any +// case, it's not guaranteed that all the remaining fields following +// the problematic one will be unmarshaled into the target object. +// +// The JSON null value unmarshals into an interface, map, pointer, or slice +// by setting that Go value to nil. Because null is often used in JSON to mean +// ``not present,'' unmarshaling a JSON null into any other Go type has no effect +// on the value and produces no error. +// +// When unmarshaling quoted strings, invalid UTF-8 or +// invalid UTF-16 surrogate pairs are not treated as an error. +// Instead, they are replaced by the Unicode replacement +// character U+FFFD. +// +func Unmarshal(data []byte, v interface{}) error { + return unmarshal(data, v) +} + +// UnmarshalContext parses the JSON-encoded data and stores the result +// in the value pointed to by v. If you implement the UnmarshalerContext interface, +// call it with ctx as an argument. +func UnmarshalContext(ctx context.Context, data []byte, v interface{}, optFuncs ...DecodeOptionFunc) error { + return unmarshalContext(ctx, data, v) +} + +func UnmarshalWithOption(data []byte, v interface{}, optFuncs ...DecodeOptionFunc) error { + return unmarshal(data, v, optFuncs...) +} + +func UnmarshalNoEscape(data []byte, v interface{}, optFuncs ...DecodeOptionFunc) error { + return unmarshalNoEscape(data, v, optFuncs...) +} + +// A Token holds a value of one of these types: +// +// Delim, for the four JSON delimiters [ ] { } +// bool, for JSON booleans +// float64, for JSON numbers +// Number, for JSON numbers +// string, for JSON string literals +// nil, for JSON null +// +type Token = json.Token + +// A Number represents a JSON number literal. +type Number = json.Number + +// RawMessage is a raw encoded JSON value. +// It implements Marshaler and Unmarshaler and can +// be used to delay JSON decoding or precompute a JSON encoding. +type RawMessage = json.RawMessage + +// A Delim is a JSON array or object delimiter, one of [ ] { or }. +type Delim = json.Delim + +// Compact appends to dst the JSON-encoded src with +// insignificant space characters elided. +func Compact(dst *bytes.Buffer, src []byte) error { + return encoder.Compact(dst, src, false) +} + +// Indent appends to dst an indented form of the JSON-encoded src. +// Each element in a JSON object or array begins on a new, +// indented line beginning with prefix followed by one or more +// copies of indent according to the indentation nesting. +// The data appended to dst does not begin with the prefix nor +// any indentation, to make it easier to embed inside other formatted JSON data. +// Although leading space characters (space, tab, carriage return, newline) +// at the beginning of src are dropped, trailing space characters +// at the end of src are preserved and copied to dst. +// For example, if src has no trailing spaces, neither will dst; +// if src ends in a trailing newline, so will dst. +func Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error { + return encoder.Indent(dst, src, prefix, indent) +} + +// HTMLEscape appends to dst the JSON-encoded src with <, >, &, U+2028 and U+2029 +// characters inside string literals changed to \u003c, \u003e, \u0026, \u2028, \u2029 +// so that the JSON will be safe to embed inside HTML