feedx 0.11.0 → 0.12.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.editorconfig +3 -0
- data/.github/workflows/test.yml +60 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +15 -4
- data/Gemfile +0 -2
- data/Gemfile.lock +80 -50
- data/Makefile +6 -6
- data/README.md +1 -1
- data/compression.go +18 -0
- data/compression_test.go +14 -2
- data/consumer_test.go +2 -2
- data/ext/parquet/decoder.go +170 -0
- data/ext/parquet/decoder_test.go +88 -0
- data/ext/parquet/go.mod +10 -0
- data/ext/parquet/go.sum +152 -0
- data/ext/parquet/parquet.go +78 -0
- data/ext/parquet/parquet_test.go +28 -0
- data/ext/parquet/reader.go +89 -0
- data/ext/parquet/testdata/alltypes_plain.parquet +0 -0
- data/ext/parquet/types.go +51 -0
- data/feedx.gemspec +5 -6
- data/feedx_test.go +2 -2
- data/format.go +45 -15
- data/format_test.go +4 -2
- data/go.mod +10 -5
- data/go.sum +90 -25
- data/internal/testdata/testdata.pb.go +176 -77
- data/lib/feedx/cache/abstract.rb +2 -2
- data/lib/feedx/cache/memory.rb +1 -0
- data/lib/feedx/compression/abstract.rb +2 -2
- data/lib/feedx/compression/gzip.rb +2 -2
- data/lib/feedx/compression/none.rb +2 -2
- data/lib/feedx/consumer.rb +15 -9
- data/lib/feedx/format.rb +4 -1
- data/lib/feedx/producer.rb +27 -22
- data/lib/feedx/stream.rb +30 -13
- data/producer_test.go +2 -2
- data/reader_test.go +2 -2
- data/spec/feedx/cache/memory_spec.rb +2 -2
- data/spec/feedx/cache/value_spec.rb +1 -1
- data/spec/feedx/compression/gzip_spec.rb +1 -1
- data/spec/feedx/compression/none_spec.rb +1 -1
- data/spec/feedx/compression_spec.rb +2 -2
- data/spec/feedx/consumer_spec.rb +5 -4
- data/spec/feedx/format/abstract_spec.rb +2 -1
- data/spec/feedx/format/json_spec.rb +6 -6
- data/spec/feedx/format/parquet_spec.rb +1 -1
- data/spec/feedx/format/protobuf_spec.rb +1 -1
- data/spec/feedx/format_spec.rb +2 -2
- data/spec/feedx/producer_spec.rb +15 -8
- data/spec/feedx/stream_spec.rb +36 -18
- data/writer_test.go +2 -2
- metadata +24 -23
- data/.travis.yml +0 -24
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c1c91575fbae6b3b5df7c840d8355ec2d27916212a57d19192fe63288b39ed9e
|
4
|
+
data.tar.gz: e21dffcc3da9ebadd5f936380a00427339566bde0d058e66498528f9418942d6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d8f0e86db26b77894b062a9919c6f902ddb6123f218fdb9233ab8126b0905c023ba8a32d69cc90b3f035345e637cb6719bd43bee984f3f8c62460772f941405f
|
7
|
+
data.tar.gz: 7451b7e3305ce7ec05a8f7c7d4a8cd9a8b65b1eef417f419903f139d01db94cc75045e0fac105eac4dc78699e2012c7c1450b16ad213615fe563799cb7ab1fab
|
data/.editorconfig
CHANGED
@@ -0,0 +1,60 @@
|
|
1
|
+
name: Test
|
2
|
+
on:
|
3
|
+
push:
|
4
|
+
branches:
|
5
|
+
- main
|
6
|
+
pull_request:
|
7
|
+
branches:
|
8
|
+
- main
|
9
|
+
jobs:
|
10
|
+
go:
|
11
|
+
runs-on: ubuntu-latest
|
12
|
+
strategy:
|
13
|
+
matrix:
|
14
|
+
go-version: [1.15.x, 1.16.x]
|
15
|
+
steps:
|
16
|
+
- name: Fetch staticcheck
|
17
|
+
uses: engineerd/configurator@v0.0.6
|
18
|
+
with:
|
19
|
+
name: staticcheck
|
20
|
+
fromGitHubReleases: true
|
21
|
+
repo: dominikh/go-tools
|
22
|
+
version: latest
|
23
|
+
urlTemplate: "https://github.com/dominikh/go-tools/releases/download/2020.2.3/staticcheck_linux_amd64.tar.gz"
|
24
|
+
pathInArchive: staticcheck/staticcheck
|
25
|
+
token: ${{ secrets.GITHUB_TOKEN }}
|
26
|
+
- name: Checkout
|
27
|
+
uses: actions/checkout@v2
|
28
|
+
- name: Cache dependencies
|
29
|
+
uses: actions/cache@v2
|
30
|
+
with:
|
31
|
+
path: ~/go/pkg/mod
|
32
|
+
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
33
|
+
restore-keys: |
|
34
|
+
${{ runner.os }}-go-
|
35
|
+
- name: Setup Go
|
36
|
+
uses: actions/setup-go@v2
|
37
|
+
with:
|
38
|
+
go-version: ${{ matrix.go-version }}
|
39
|
+
- name: Run tests
|
40
|
+
run: make test
|
41
|
+
- name: Run staticcheck
|
42
|
+
run: make staticcheck
|
43
|
+
ruby:
|
44
|
+
runs-on: ubuntu-latest
|
45
|
+
strategy:
|
46
|
+
matrix:
|
47
|
+
ruby-version: ["2.6", "2.7", "3.0"]
|
48
|
+
steps:
|
49
|
+
- name: Install libarrow
|
50
|
+
run: |
|
51
|
+
wget https://apache.bintray.com/arrow/$(lsb_release --id --short | tr 'A-Z' 'a-z')/apache-arrow-archive-keyring-latest-$(lsb_release --codename --short).deb
|
52
|
+
sudo apt install -y ./apache-arrow-archive-keyring-latest-$(lsb_release --codename --short).deb
|
53
|
+
sudo apt update
|
54
|
+
sudo apt install -y libarrow-dev libarrow-glib-dev libarrow-dataset-dev libplasma-dev libplasma-glib-dev libgandiva-dev libgandiva-glib-dev libparquet-dev libparquet-glib-dev
|
55
|
+
- uses: actions/checkout@v2
|
56
|
+
- uses: ruby/setup-ruby@v1
|
57
|
+
with:
|
58
|
+
ruby-version: ${{ matrix.ruby-version }}
|
59
|
+
bundler-cache: true
|
60
|
+
- run: bundle exec rake
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
@@ -1,6 +1,17 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
inherit_gem:
|
2
|
+
rubocop-bsm:
|
3
|
+
- default.yml
|
4
|
+
inherit_mode:
|
5
|
+
merge:
|
6
|
+
- Exclude
|
4
7
|
|
5
8
|
AllCops:
|
6
|
-
TargetRubyVersion:
|
9
|
+
TargetRubyVersion: 2.6
|
10
|
+
Naming/MethodParameterName:
|
11
|
+
MinNameLength: 2
|
12
|
+
Naming/MemoizedInstanceVariableName:
|
13
|
+
Enabled: false
|
14
|
+
Naming/FileName:
|
15
|
+
Exclude: [lib/sortable-by.rb]
|
16
|
+
Metrics/ParameterLists:
|
17
|
+
Max: 8
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,70 +1,102 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
feedx (0.
|
5
|
-
bfs (>= 0.
|
4
|
+
feedx (0.12.5)
|
5
|
+
bfs (>= 0.8.0)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
9
9
|
specs:
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
10
|
+
activesupport (6.1.3.1)
|
11
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
12
|
+
i18n (>= 1.6, < 2)
|
13
|
+
minitest (>= 5.1)
|
14
|
+
tzinfo (~> 2.0)
|
15
|
+
zeitwerk (~> 2.3)
|
16
|
+
ast (2.4.2)
|
17
|
+
bfs (0.8.1)
|
18
|
+
bigdecimal (3.0.2)
|
19
|
+
concurrent-ruby (1.1.8)
|
20
|
+
diff-lcs (1.4.4)
|
21
|
+
extpp (0.0.9)
|
22
|
+
gio2 (3.4.4)
|
23
|
+
gobject-introspection (= 3.4.4)
|
24
|
+
glib2 (3.4.4)
|
17
25
|
native-package-installer (>= 1.0.3)
|
18
26
|
pkg-config (>= 1.3.5)
|
19
|
-
gobject-introspection (3.4.
|
20
|
-
glib2 (= 3.4.
|
21
|
-
google-protobuf (3.
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
+
gobject-introspection (3.4.4)
|
28
|
+
glib2 (= 3.4.4)
|
29
|
+
google-protobuf (3.15.8)
|
30
|
+
i18n (1.8.10)
|
31
|
+
concurrent-ruby (~> 1.0)
|
32
|
+
minitest (5.14.4)
|
33
|
+
native-package-installer (1.1.1)
|
34
|
+
parallel (1.20.1)
|
35
|
+
parser (3.0.1.1)
|
36
|
+
ast (~> 2.4.1)
|
37
|
+
pbio (0.2.2)
|
27
38
|
google-protobuf
|
28
|
-
pkg-config (1.4.
|
39
|
+
pkg-config (1.4.6)
|
40
|
+
rack (2.2.3)
|
29
41
|
rainbow (3.0.0)
|
30
|
-
rake (13.0.
|
31
|
-
red-arrow (0.
|
42
|
+
rake (13.0.3)
|
43
|
+
red-arrow (3.0.0)
|
44
|
+
bigdecimal (>= 2.0.3)
|
32
45
|
extpp (>= 0.0.7)
|
33
46
|
gio2 (>= 3.3.6)
|
34
47
|
native-package-installer
|
35
48
|
pkg-config
|
36
|
-
red-parquet (0.
|
37
|
-
red-arrow (= 0.
|
38
|
-
regexp_parser (1.
|
39
|
-
rexml (3.2.
|
40
|
-
rspec (3.
|
41
|
-
rspec-core (~> 3.
|
42
|
-
rspec-expectations (~> 3.
|
43
|
-
rspec-mocks (~> 3.
|
44
|
-
rspec-core (3.
|
45
|
-
rspec-support (~> 3.
|
46
|
-
rspec-expectations (3.
|
49
|
+
red-parquet (3.0.0)
|
50
|
+
red-arrow (= 3.0.0)
|
51
|
+
regexp_parser (2.1.1)
|
52
|
+
rexml (3.2.5)
|
53
|
+
rspec (3.10.0)
|
54
|
+
rspec-core (~> 3.10.0)
|
55
|
+
rspec-expectations (~> 3.10.0)
|
56
|
+
rspec-mocks (~> 3.10.0)
|
57
|
+
rspec-core (3.10.1)
|
58
|
+
rspec-support (~> 3.10.0)
|
59
|
+
rspec-expectations (3.10.1)
|
47
60
|
diff-lcs (>= 1.2.0, < 2.0)
|
48
|
-
rspec-support (~> 3.
|
49
|
-
rspec-mocks (3.
|
61
|
+
rspec-support (~> 3.10.0)
|
62
|
+
rspec-mocks (3.10.2)
|
50
63
|
diff-lcs (>= 1.2.0, < 2.0)
|
51
|
-
rspec-support (~> 3.
|
52
|
-
rspec-support (3.
|
53
|
-
rubocop (
|
64
|
+
rspec-support (~> 3.10.0)
|
65
|
+
rspec-support (3.10.2)
|
66
|
+
rubocop (1.13.0)
|
54
67
|
parallel (~> 1.10)
|
55
|
-
parser (>=
|
68
|
+
parser (>= 3.0.0.0)
|
56
69
|
rainbow (>= 2.2.2, < 4.0)
|
57
|
-
regexp_parser (>= 1.
|
70
|
+
regexp_parser (>= 1.8, < 3.0)
|
58
71
|
rexml
|
59
|
-
rubocop-ast (>= 0.0
|
72
|
+
rubocop-ast (>= 1.2.0, < 2.0)
|
60
73
|
ruby-progressbar (~> 1.7)
|
61
|
-
unicode-display_width (>= 1.4.0, <
|
62
|
-
rubocop-ast (
|
63
|
-
parser (>=
|
64
|
-
rubocop-
|
65
|
-
rubocop (
|
66
|
-
|
67
|
-
|
74
|
+
unicode-display_width (>= 1.4.0, < 3.0)
|
75
|
+
rubocop-ast (1.5.0)
|
76
|
+
parser (>= 3.0.1.1)
|
77
|
+
rubocop-bsm (0.5.9)
|
78
|
+
rubocop (~> 1.0)
|
79
|
+
rubocop-performance
|
80
|
+
rubocop-rails
|
81
|
+
rubocop-rake
|
82
|
+
rubocop-rspec
|
83
|
+
rubocop-performance (1.11.1)
|
84
|
+
rubocop (>= 1.7.0, < 2.0)
|
85
|
+
rubocop-ast (>= 0.4.0)
|
86
|
+
rubocop-rails (2.9.1)
|
87
|
+
activesupport (>= 4.2.0)
|
88
|
+
rack (>= 1.1)
|
89
|
+
rubocop (>= 0.90.0, < 2.0)
|
90
|
+
rubocop-rake (0.5.1)
|
91
|
+
rubocop
|
92
|
+
rubocop-rspec (2.3.0)
|
93
|
+
rubocop (~> 1.0)
|
94
|
+
rubocop-ast (>= 1.1.0)
|
95
|
+
ruby-progressbar (1.11.0)
|
96
|
+
tzinfo (2.0.4)
|
97
|
+
concurrent-ruby (~> 1.0)
|
98
|
+
unicode-display_width (2.0.0)
|
99
|
+
zeitwerk (2.4.2)
|
68
100
|
|
69
101
|
PLATFORMS
|
70
102
|
ruby
|
@@ -72,13 +104,11 @@ PLATFORMS
|
|
72
104
|
DEPENDENCIES
|
73
105
|
bundler
|
74
106
|
feedx!
|
75
|
-
google-protobuf (>= 3.7.0.pre.rc2)
|
76
107
|
pbio
|
77
108
|
rake
|
78
|
-
red-parquet
|
109
|
+
red-parquet (>= 3.0, < 4.0)
|
79
110
|
rspec
|
80
|
-
rubocop
|
81
|
-
rubocop-performance
|
111
|
+
rubocop-bsm
|
82
112
|
|
83
113
|
BUNDLED WITH
|
84
114
|
2.1.4
|
data/Makefile
CHANGED
@@ -1,12 +1,12 @@
|
|
1
|
-
default:
|
1
|
+
default: test
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
.common.makefile:
|
4
|
+
curl -fsSL -o $@ https://gitlab.com/bsm/misc/raw/master/make/go/common.makefile
|
5
5
|
|
6
|
-
|
7
|
-
go vet ./...
|
6
|
+
include .common.makefile
|
8
7
|
|
9
8
|
proto: internal/testdata/testdata.pb.go
|
10
9
|
|
11
10
|
%.pb.go: %.proto
|
12
|
-
|
11
|
+
# may need to `go install google.golang.org/protobuf/cmd/protoc-gen-go`
|
12
|
+
protoc -I=. --go_out=paths=source_relative:. $<
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Feedx
|
2
2
|
|
3
|
-
[](https://github.com/bsm/feedx/actions/workflows/test.yml)
|
4
4
|
[](https://opensource.org/licenses/Apache-2.0)
|
5
5
|
|
6
6
|
Feed-based data exchange between services.
|
data/compression.go
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
package feedx
|
2
2
|
|
3
3
|
import (
|
4
|
+
"compress/flate"
|
4
5
|
"compress/gzip"
|
5
6
|
"io"
|
6
7
|
"path"
|
@@ -20,6 +21,8 @@ func DetectCompression(name string) Compression {
|
|
20
21
|
ext := path.Ext(path.Base(name))
|
21
22
|
if ext != "" && ext[0] == '.' && ext[len(ext)-1] == 'z' {
|
22
23
|
return GZipCompression
|
24
|
+
} else if ext == ".flate" {
|
25
|
+
return FlateCompression
|
23
26
|
}
|
24
27
|
}
|
25
28
|
return NoCompression
|
@@ -61,3 +64,18 @@ func (gzipCompression) NewReader(r io.Reader) (io.ReadCloser, error) {
|
|
61
64
|
func (gzipCompression) NewWriter(w io.Writer) (io.WriteCloser, error) {
|
62
65
|
return gzip.NewWriter(w), nil
|
63
66
|
}
|
67
|
+
|
68
|
+
// --------------------------------------------------------------------
|
69
|
+
|
70
|
+
// FlateCompression supports flate compression format.
|
71
|
+
var FlateCompression = flateCompression{}
|
72
|
+
|
73
|
+
type flateCompression struct{}
|
74
|
+
|
75
|
+
func (flateCompression) NewReader(r io.Reader) (io.ReadCloser, error) {
|
76
|
+
return flate.NewReader(r), nil
|
77
|
+
}
|
78
|
+
|
79
|
+
func (flateCompression) NewWriter(w io.Writer) (io.WriteCloser, error) {
|
80
|
+
return flate.NewWriter(w, flate.BestSpeed)
|
81
|
+
}
|
data/compression_test.go
CHANGED
@@ -4,8 +4,8 @@ import (
|
|
4
4
|
"bytes"
|
5
5
|
|
6
6
|
"github.com/bsm/feedx"
|
7
|
-
. "github.com/
|
8
|
-
. "github.com/
|
7
|
+
. "github.com/bsm/ginkgo"
|
8
|
+
. "github.com/bsm/gomega"
|
9
9
|
)
|
10
10
|
|
11
11
|
var _ = Describe("Compression", func() {
|
@@ -41,6 +41,9 @@ var _ = Describe("Compression", func() {
|
|
41
41
|
Expect(feedx.DetectCompression("/path/to/file.pb.gz")).To(Equal(feedx.GZipCompression))
|
42
42
|
Expect(feedx.DetectCompression("/path/to/file.pbz")).To(Equal(feedx.GZipCompression))
|
43
43
|
|
44
|
+
Expect(feedx.DetectCompression("/path/to/file.flate")).To(Equal(feedx.FlateCompression))
|
45
|
+
Expect(feedx.DetectCompression("/path/to/file.whatever.flate")).To(Equal(feedx.FlateCompression))
|
46
|
+
|
44
47
|
Expect(feedx.DetectCompression("")).To(Equal(feedx.NoCompression))
|
45
48
|
Expect(feedx.DetectCompression("/path/to/file")).To(Equal(feedx.NoCompression))
|
46
49
|
Expect(feedx.DetectCompression("/path/to/file.txt")).To(Equal(feedx.NoCompression))
|
@@ -63,4 +66,13 @@ var _ = Describe("Compression", func() {
|
|
63
66
|
runSharedTest(subject)
|
64
67
|
})
|
65
68
|
})
|
69
|
+
|
70
|
+
Describe("FlateCompression", func() {
|
71
|
+
var subject = feedx.FlateCompression
|
72
|
+
var _ feedx.Compression = subject
|
73
|
+
|
74
|
+
It("should write/read", func() {
|
75
|
+
runSharedTest(subject)
|
76
|
+
})
|
77
|
+
})
|
66
78
|
})
|
data/consumer_test.go
CHANGED
@@ -8,8 +8,8 @@ import (
|
|
8
8
|
"github.com/bsm/bfs"
|
9
9
|
"github.com/bsm/feedx"
|
10
10
|
"github.com/bsm/feedx/internal/testdata"
|
11
|
-
. "github.com/
|
12
|
-
. "github.com/
|
11
|
+
. "github.com/bsm/ginkgo"
|
12
|
+
. "github.com/bsm/gomega"
|
13
13
|
)
|
14
14
|
|
15
15
|
var _ = Describe("Consumer", func() {
|
@@ -0,0 +1,170 @@
|
|
1
|
+
package parquet
|
2
|
+
|
3
|
+
import (
|
4
|
+
"encoding/binary"
|
5
|
+
"fmt"
|
6
|
+
"io"
|
7
|
+
"reflect"
|
8
|
+
"time"
|
9
|
+
|
10
|
+
kpq "github.com/bsm/parquet-go/parquet"
|
11
|
+
)
|
12
|
+
|
13
|
+
type decoder struct {
|
14
|
+
cols []*columnReader
|
15
|
+
closers []io.Closer
|
16
|
+
}
|
17
|
+
|
18
|
+
func newDecoder(rs io.ReadSeeker, names []string, batchSize int) (*decoder, error) {
|
19
|
+
file, err := kpq.FileFromReader(rs)
|
20
|
+
if err != nil {
|
21
|
+
return nil, err
|
22
|
+
}
|
23
|
+
|
24
|
+
// normalise column names
|
25
|
+
if len(names) == 0 {
|
26
|
+
for _, c := range file.Schema.Columns() {
|
27
|
+
names = append(names, c.String())
|
28
|
+
}
|
29
|
+
}
|
30
|
+
|
31
|
+
// normalise batch size
|
32
|
+
if batchSize < 1 {
|
33
|
+
batchSize = 1000
|
34
|
+
}
|
35
|
+
|
36
|
+
// initialise column buffers
|
37
|
+
cols := make([]*columnReader, 0, len(names))
|
38
|
+
for _, name := range names {
|
39
|
+
col, ok := file.Schema.ColumnByName(name)
|
40
|
+
if !ok {
|
41
|
+
_ = file.Close()
|
42
|
+
return nil, fmt.Errorf("column %q does not exist", name)
|
43
|
+
}
|
44
|
+
cols = append(cols, newColumnReader(file, col, batchSize))
|
45
|
+
}
|
46
|
+
|
47
|
+
return &decoder{cols: cols, closers: []io.Closer{file}}, nil
|
48
|
+
}
|
49
|
+
|
50
|
+
func (w *decoder) Decode(v interface{}) error {
|
51
|
+
rv := reflect.ValueOf(v)
|
52
|
+
rt := rv.Type()
|
53
|
+
if rt.Kind() != reflect.Ptr {
|
54
|
+
return fmt.Errorf("cannot decode non-pointer %s type", rt.String())
|
55
|
+
}
|
56
|
+
|
57
|
+
// field index by name
|
58
|
+
fidx := cachedTypeFields(rt.Elem())
|
59
|
+
elem := rv.Elem()
|
60
|
+
|
61
|
+
for _, r := range w.cols {
|
62
|
+
// next column value
|
63
|
+
val, err := r.Next()
|
64
|
+
if err != nil {
|
65
|
+
return err
|
66
|
+
}
|
67
|
+
|
68
|
+
// skip if value is NULL
|
69
|
+
if val == nil {
|
70
|
+
continue
|
71
|
+
}
|
72
|
+
|
73
|
+
// set field if exists
|
74
|
+
if fi, ok := fidx[r.Name()]; ok {
|
75
|
+
fv := elem.Field(fi)
|
76
|
+
if ok := setValue(fv, val); !ok {
|
77
|
+
return fmt.Errorf("cannot assign value of type %T to %s", val, fv.Type())
|
78
|
+
}
|
79
|
+
}
|
80
|
+
}
|
81
|
+
|
82
|
+
return nil
|
83
|
+
}
|
84
|
+
|
85
|
+
func (w *decoder) Close() (err error) {
|
86
|
+
for _, c := range w.closers {
|
87
|
+
if e := c.Close(); e != nil {
|
88
|
+
err = e
|
89
|
+
}
|
90
|
+
}
|
91
|
+
return
|
92
|
+
}
|
93
|
+
|
94
|
+
// --------------------------------------------------------------------
|
95
|
+
|
96
|
+
func setValue(rv reflect.Value, v interface{}) bool {
|
97
|
+
if rv.Kind() == reflect.Ptr {
|
98
|
+
if rv.IsNil() {
|
99
|
+
if ev := reflect.New(rv.Type().Elem()); setValue(ev, v) {
|
100
|
+
rv.Set(ev)
|
101
|
+
return true
|
102
|
+
}
|
103
|
+
return false
|
104
|
+
}
|
105
|
+
return setValue(rv.Elem(), v)
|
106
|
+
}
|
107
|
+
|
108
|
+
switch vv := v.(type) {
|
109
|
+
case bool:
|
110
|
+
switch rv.Kind() {
|
111
|
+
case reflect.Bool:
|
112
|
+
rv.SetBool(vv)
|
113
|
+
return true
|
114
|
+
}
|
115
|
+
case []byte:
|
116
|
+
switch rv.Kind() {
|
117
|
+
case reflect.String:
|
118
|
+
rv.SetString(string(vv))
|
119
|
+
return true
|
120
|
+
case reflect.Slice:
|
121
|
+
if rv.Type() == byteSliceType {
|
122
|
+
rv.SetBytes(vv)
|
123
|
+
return true
|
124
|
+
}
|
125
|
+
}
|
126
|
+
case int, int8, int16, int32, int64:
|
127
|
+
switch rv.Kind() {
|
128
|
+
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
129
|
+
rv.SetInt(reflect.ValueOf(v).Int())
|
130
|
+
return true
|
131
|
+
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
132
|
+
rv.SetUint(uint64(reflect.ValueOf(v).Int()))
|
133
|
+
return true
|
134
|
+
}
|
135
|
+
case uint, uint8, uint16, uint32, uint64:
|
136
|
+
switch rv.Kind() {
|
137
|
+
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
138
|
+
rv.SetInt(int64(reflect.ValueOf(v).Uint()))
|
139
|
+
return true
|
140
|
+
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
141
|
+
rv.SetUint(reflect.ValueOf(v).Uint())
|
142
|
+
return true
|
143
|
+
}
|
144
|
+
case float32, float64:
|
145
|
+
switch rv.Kind() {
|
146
|
+
case reflect.Float32, reflect.Float64:
|
147
|
+
rv.SetFloat(reflect.ValueOf(v).Float())
|
148
|
+
return true
|
149
|
+
}
|
150
|
+
case kpq.Int96:
|
151
|
+
if rt := rv.Type(); rt == timeType {
|
152
|
+
ns := int64(binary.LittleEndian.Uint64(vv[:8]))
|
153
|
+
jd := int64(binary.LittleEndian.Uint32(vv[8:]))
|
154
|
+
ts := time.Unix((jd-2440588)*86400, ns)
|
155
|
+
rv.Set(reflect.ValueOf(ts))
|
156
|
+
return true
|
157
|
+
} else if rt == int96Type {
|
158
|
+
rv.Set(reflect.ValueOf(v))
|
159
|
+
return true
|
160
|
+
}
|
161
|
+
}
|
162
|
+
|
163
|
+
return false
|
164
|
+
}
|
165
|
+
|
166
|
+
var (
|
167
|
+
byteSliceType = reflect.TypeOf(([]byte)(nil))
|
168
|
+
int96Type = reflect.TypeOf(kpq.Int96{})
|
169
|
+
timeType = reflect.TypeOf(time.Time{})
|
170
|
+
)
|